Project Files

HTML file is the most readable and has intractable graphs, but the source code of all the figures is hidden for clarity.

RMD file contains all the source code.

PDF file is just a pdf version of the RMD file.

library(ggplot2)
library(gridExtra)
library(tidyverse)
library(grid)
library(lattice)
library(plotly)
library(kableExtra)
library(GGally)
library(viridis)
library(emmeans)
library(car)


# Colors
colors_3 = c(viridis(25)[4], viridis(25)[10], viridis(25)[15], viridis(25)[19])
colors_4 = c(viridis(25)[1], viridis(25)[4], viridis(25)[10], viridis(25)[15], viridis(25)[19])


1. Describe your research scenario and questions(s).


A restaurant chain is changing its menu by adding a few new items. The restaurant wantx to test three different marketing campaigns they are thinking about using to promote their new menu items. The restaurant wants to determine which promotion has the greatest effect on sales of new menu items. The restaurant locations in which the campaigns will be tested are selected at random. Each randomly selected location will begin serving the new menu items, and run one of the three marketing campaigns, also chosen at random. The weekly sales of the new menu items are recorded for the first four weeks of the marketing campaign.

The restaurant chain is hiring a data scientist to evaluate the effectiveness of three different marketing campaigns. The restaurant wants to determine which of the three marketing strategies is most effective at increasing sales of new menu items, so they can confidently implement said marketing campaign at all their restaurant locations.

Research Question: Which marketing campaign(s) results in the greatest increase in sales of new menu items for the restaurant chain?

Many auxillary questions will be answered in our journey to answer the above question, but the above question is the core, guiding inquiry of our investigation.



2. Describe the data set.

Data Source: https://www.kaggle.com/datasets/chebotinaa/fast-food-marketing-campaign-ab-test?resource=download

# Input Data from csv file.
data = read.csv(file = "WA_Marketing-Campaign.csv", header = TRUE); data

# Factor the Data to make it easier to work with.
data$Promotion = factor(data$Promotion); data$Promotion
levels(data$Promotion)
data$week = factor(data$week)
levels(data$week)
tibble(data)

# Create Subsets for each Marketing Campaign to make our life easier.
promo_1 = filter(data, Promotion == 1); promo_1
promo_2 = filter(data, Promotion == 2); promo_2
promo_3 = filter(data, Promotion == 3); promo_3

# Data was luckily very clean, not a lot of data cleaning was necessary.


Description Values
MarketID Unique identifier for market. Range(1:10)
MarketSize Size of market area by sales Small, Medium, Large.
LocationID Unique identifier for store location
AgeOfStore Age of store in years
Promotion One of three promotions that were tested Range(1:3)
week One of four weeks when the promotions were run Range(1:4)
SalesInThousands Sales amount for a specific LocationID, Promotion, and week


SalesInThousands

Lets first look at the SalesInThousands variable for each of the three marketing campaigns. The SalesInThousands variable is the sales amount in thousands of new menu items for a specific restaurant.

Exploratory Question: Are the sales of new menu items similar for each marketing campaign group?

# Summary Statistics
# Mean
mean_1 = mean(promo_1$SalesInThousands); mean_1
mean_2 = mean(promo_2$SalesInThousands); mean_2
mean_3 = mean(promo_3$SalesInThousands); mean_3
mean_tot = mean(data$SalesInThousands); mean_tot

# Standard Deviation
std_1 = sd(promo_1$SalesInThousands); std_1
std_2 = sd(promo_2$SalesInThousands); std_2
std_3 = sd(promo_3$SalesInThousands); std_3
std_tot = sd(data$SalesInThousands); std_tot

# Number of Samples
n = nrow(data); n
k = length(levels(data$Promotion))
n_1 = nrow(promo_1); n_1
n_2 = nrow(promo_2); n_2
n_3 = nrow(promo_3); n_3
Marketing Campaign Sales (In Thousands) Standard Deviation Population
Promo 1 58.10 16.55 172
Promo 2 47.33 15.11 188
Promo 3 55.36 16.77 188
Total 53.47 16.75 548

Table 1.0: Summary statistics for sales of new menu items for all restaurants participating in the new marketing campaigns.


The three different marketing campaigns subsets (Promotion 1, Promotion 2, and Promotion 3) have very symmetric data, all having similar means, standard deviations and population sizes seen in Table 1.0. Lets create a boxplot to visualize this symmetry.

Figure 1.0: Box plot showing the difference in restaurant sales data for each of the three marketing campaigns. Promotion 1 is in purple, Promotion 2 is in green, and Promotion 3 is in yellow.


Promotion 1 has the highest mean sales of new menu items, followed by Promotion 3 and then Promotion 2. All have similar variance, which is important when comparing means. However, there seems to be more Promotion 2 outliers. Lets see if that is true.

# Identify Outliers using IQR Methology

IQR = summary(promo_1$SalesInThousands)[5] - summary(promo_1$SalesInThousands)[2]; IQR
outliers = filter(promo_1, SalesInThousands > summary(promo_1$SalesInThousands)[5] + (1.5 * IQR) | SalesInThousands < summary(promo_1$SalesInThousands)[3] - (1.5 * IQR)); outliers$SalesInThousands

IQR = summary(promo_2$SalesInThousands)[5] - summary(promo_2$SalesInThousands)[2]; IQR
outliers_2 = filter(promo_2, SalesInThousands > summary(promo_2$SalesInThousands)[5] + (1.5 * IQR) | SalesInThousands < summary(promo_2$SalesInThousands)[3] - (1.5 * IQR)); outliers_2$SalesInThousands

IQR = summary(promo_3$SalesInThousands)[5] - summary(promo_3$SalesInThousands)[2]; IQR
outliers_3 = filter(promo_3, SalesInThousands > summary(promo_3$SalesInThousands)[5] + (1.5 * IQR) | SalesInThousands < summary(promo_3$SalesInThousands)[3] - (1.5 * IQR)); outliers_3$SalesInThousands

nrow(outliers)
nrow(outliers_2)
nrow(outliers_3)

Using the IQR methodology to identity outliers, we observed 12 sales outliers each for both Promotion 1 and 2, and 30 sales outliers for Promotion 3. This is an imbalance we should keep in mind and circle back to before we make any final conclusions about our data.

To answer our exploratory question, the sales of new menu items were in fact similar for each marketing campaign group but not the same. Promotion 2 looks to deviate from Promotion 1 and Promotion 2, and we will test to see if that deviation is significant.


AgeOfStore

Lets next look at the AgeOfStore variable for each of the three marketing campaigns. The AgeOfStore variable is age of each restaurant in the study.

Exploratory Question: Are age of restaurant distributed different in each marketing campaign group?

Figure 2.0: Scatter plot showing the relationship between AgeOfStore (x) and SalesInThousands (y) for all restaurants conducting marketing campaigns for new menu items. Double-click on the legend to view individual marketing campaigns.


Looking at the scatter plot of age and sales for restaurants we observe no clear linear relationship between the two variables. We can confirm this with a calculation of the correlation coefficient, \(r\).

# Correlation Coefficient
cor(x=data$AgeOfStore, y=data$SalesInThousands)

Our the calculated correlation coefficient, \(r\), of store age and store sales is \(-0.029\), which is almost zero, meaning there is little to no linear relationship between the two variables.

# Age Summary Statistic
tapply(data$AgeOfStore, data$Promotion, summary)

summary(promo_1$AgeOfStore)
sd(promo_1$AgeOfStore)
summary(promo_2$AgeOfStore)
sd(promo_2$AgeOfStore)
summary(promo_3$AgeOfStore)
sd(promo_3$AgeOfStore)
Promo 1 Promo 2 Promo 3
Mean 8.28 7.98 9.23
Median 6 7 8
Standard Deviation 6.64 6.60 6.65
(Min, Max) (1, 27) (1, 28) (1, 24)
(Q1, Q3) (3, 12) (2, 10) (5, 12)

Table 2.0: Summary statistics for store age for all restaurants participating in the marketing campaign study.


Figure 3.0: Box plot showing the difference in restaurant age data for each of the three marketing campaigns. Promotion 1 is in purple, Promotion 2 is in green, and Promotion 3 is in yellow.


Both Table 2.0 and Figure 3.0 show that the age distributions among the three marketing campaign is very similar. Promotion 1, 2 and 3 have a mean ages of \(8.28\), \(7.98\), and \(9.23\) respectively and all have standard deviations \(\sim 6.0\). All have some clustering around age \(1\), and have some outliers above Q3. All three marketing campaigns age distributions are not identical but very similar for real world data standards. To answer our exploratory question, the age of restaurant is not distributed significantly different in each marketing campaign.


MarketSize

Lets next look at the MarketSize variable for each of the three marketing campaigns. The MarketSize variable is a categorical variable that describes the market size of each restaurant. There are three market sizes: small, medium and large. The thresholds and criteria for categorization are unknown.

Exploratory Question: Are market size proportions similar in each marketing campaign group?

Figure 4.0: Stacked bar plot showing the difference in total sales between marketing campaigns stratified by market size.


For all three campaigns the greatest proportion of total sales can be attributed to medium market restaurants, large market restaurants are the next biggest contributor to total sale of new menu items, and small market restaurants contributioned the least amount. The overall trend is similar for all three marketing campaigns.

Figure 5.0: Stacked bar plot showing the differences in amount of restaurant in each of the three market sizes (small, medium, large) for each of the three marketing campaigns.


Each marketing campaign has the most amount of medium market restaurants followed by large market restaurants, and the least small market restaurants. Promotion 1, Promotion 2, and Promotion 3 had \(56\), \(64\), and \(48\) large market restaurants respectively, \(96\), \(108\), and \(116\) medium market restaurants respectively, and \(20\), \(16\), and \(24\) small market restaurants respectively. The overall trend is similar for all three marketing campaigns.

Lets consolidate these trends in Figure 4.0 and Figure 5.0 into one scatter plot, to best visualize the different amount of restaurants in each market size for each of the three marketing campaigns, and how those markets contributed to the marketing groups sales.

Figure 6.0: Scatter plot showing the relationship between Mean Sales (x) and Restaurant Count (y) for all restaurants conducting marketing campaigns for new menu items. Additionally, if you hover over each point the Total Sales of each sub group is listed.


The big take away from Figure 6.0 is that Promotion 2 had the most large market restaurants, but the lowest total large market sales (the total sales can be seen if you hover over the data point in Figure 6.0). In fact,all of Promotion 2’s restaurants, no matter the market size, under-performed, but Promotion 2’s large market restaurants were the most significant under-performing market for the Promotion 2 cohort. Figure 6.0 identifies the reason Promotion 2 has the lowest mean sales, but also shows that large market restaurants under-performed more than Promotion 2’s small and medium market restaurants.

Answering our exploratory question, the market size proportions were similar for each marketing campaign group, and each market size contributed proportionality based on their market size to the total sales of the marketing campaign group. This trend is visualized in Figure 6.0, which shows three clusters. a small market cluster, a medium market cluster, and a large market cluster. The medium market cluster had the lowest mean sales, while the large market had the highest mean sales.


Week

Lastly, lets look at the Week variable for each of the three marketing campaigns. The Week variable ranges from week 1 through week4, time stamping the four weeks of marketing campaign study. Sales amounts for each restaurant were recorded for each of the four weeks.

Exploratory Question: Are some campaigns trending differently? Low sales in week 1, and higher in week 4?

Figure 7.0: Stacked bar plot showing the difference in total sales between marketing campaigns and the four weeks of the campaign.


There are no clear differences in marketing campaign performance week to week for any of the three promotions. There are no visible trends that shows an increase or decrease in marketing campaign performance week by week for any promotion. Each promotions weekly performance from week 1 through week 4 is consistent, each week accounting for about a quarter of the monthly sales.


Overall Conclusion

The data for all three underlying populations, Promotion 1 restaurants, Promotion 2 restaurants, and Promotion 3 restaurants, is extremely similar when we look at SalesInThousands, and its relation with all the relevant variables: AgeOfStore, MarketSize, and Week. Symmetry in our data is what were are most concerned about when comparing underlying populations, and we observed no significant irregularities. We can confidently proceed to comparing the SalesInThousands means for each marketing campaign.



3. Describe the statistical methods you plan to use.

Analysis of Variance (ANOVA)

The goal of a one-way analysis of variance (ANOVA) is to compare means across groups. There are many procedures to compare means across two groups, but ANOVA is a procedure that extends this methodology to a setting where there are more than two groups. In our scenario, we have three groups, the three different marketing campaigns, and we are interesting in comparing mean sales of new menu items between the three campaigns.

It is important to remember that when we conduct an ANOVA test, we are comparing across several groups while considering all of the data together. We have three marketing campaigns, if we did not use an ANOVA test, we would likely resort to two-sample t-testing different combinations of the three marketing campaigns. However, conclusions are often different when all means are considered instead of just a pair of means. ANOVA allows us to take into account all three means before we make a conclusion. The difference in the test statistic, \(F\), from the test statistic of a two-sample t-test is fundamental to this idea of taking into account more than two means. The equation for the test statistic for an ANOVA test is shown below:

\[ F = \frac{\text{Between Group Variance}}{\text{Within Group Variance}} \]

The deviation between an individual point and the respective group mean is representative of the within group variance. In our scenario, this is the difference between the sales of an individual restaurant who is using Promotion 1 and the mean sales of all restaurant who is using Promotion 1. The deviation between the group mean and the overall mean is representative of the between group variance. In our scenario, this is the difference between the Promotion 1 mean sales and the means sales of all three marketing campaigns (and the same for the other two campaigns). These deviations are squared and the sum over all points is taken to obtain the sum of squares within and the sum of squares between, respectively.

That is a lot of words. The important take away from the above description of \(F\) is that the ANOVA methodology takes into account the overall mean when analyzing variance of a data set. And because the overall mean is a function of all groups in the data set, the ANOVA test is different than simply performing multiple two-sample t-test, which only uses the means of two groups.

A good rule of thumb when conducting ANOVA tests is if the between group variance is large and the within group variance is small, then the null hypothesis is often rejected in favor of the alternative hypothesis that the underlying means across group are not all equal. In our sales data, we observe the opposite. As seen in Figure 1.0, the between group variability is small and the within group variability is large. Following our rule of thumb above, we should expect to fail to reject our null hypothesis that the mean sales of the three marketing campaigns are equal. After we conduct our ANOVA test below, we will see if our hypothesis is correct.


Tukey’s Pairwise T-Tests

Simply put, the pairwise t-test for an ANOVA test allows us determine between which groups the differences (we deemed significant in our ANOVA test) lie. The equation for the test statistic for a Tukey’s pairwise t-test in the context of an ANOVA test is shown below:

\[t = \frac{\bar{x}_{promo-1} - \bar{x}_{promo-2}}{\sqrt{s^{2}_{p}(\frac{1}{n_{promo-1}} + \frac{1}{n_{promo-2}})}}\]

The key take away from this equation, is that the \(t\)-statistic is a function of the variance from the ANOVA, \(s^{2}_{p}\), as opposed to using the pooled estimate of the variance from only groups involved in the pairwise t-test. This is a what differentiates a Tukey’s pairwise t-tests for ANOVA from a regular two-sample t-test. If we only used the data from groups we would have ended up with a slightly different estimate of the variance, and thus a slightly different \(t\)-statistic. Because we assume that all groups have the same variance when conducting an ANOVA test, we do not want to use different estimates of the variance in each pairwise comparison.

Given that the estimate from ANOVA of the variability is based on more information (more observations are included), it will be more accurate than that obtained from using the data from just two of the groups. Our estimate of variability in an ANOVA test, \(s^{2}_{p}\), is therefore calculated from a larger sample size (all groups, not just the groups involved in the pairwise t-test). This estimate of variability is more accurate, and is one of the primary advantages of ANOVA pairwise t-tests.

Something to keep in mind when running multiple pairwise t-tests is that the more pairwise tests we run the more errors we are likely to observe due to chance alone. The more you do just about anything the more likely you are to make a mistake because everytime you do something you give yourself the opportunity to make a mistake. If you do nothing, you can’t make a mistake. In our scenario, an error is a Type I Error, a false positive conclusion (rejecting the null hypothesis when in reality the null hypothesis is in fact true).

In order to reduce the amount of Type I Errors we have to make it harder for us to reject the null hypothesis during our pairwise t-tests. One way of doing this is to increase our confidence level (decreasing \(\alpha\)). Therefore, as we increase the number of pairwise t-tests we run, we also increase our confidence level for those pairwise t-tests in order to balance out our increasing chance for errors. This allows us to maintain a specified family-wise Type I error rate. Family-wise Type I error rate meaning the error rate when looking at all pairwise t-tests, not just the Type I error rate of individual pairwise t-tests.

Procedures for controlling the family wise type I error rate at a pre-specified level are called multiple comparison procedures. Luckily for us, we are only conducting three pairwise tests, but in our ANOVA testing we will still use the Tukey multiple comparison procedure, a complex procedure that requires statistical software (we will be using R). This will reduce our Type 1 error rate.


Analysis of Covariance (ANCOVA)

Analysis of Covariance (ANCOVA) is really just a variation of a linear regression model, and an extension of the ANOVA methodology. We are still interesting in the different group means like we are when doing ANOVA, but when doing ANCOVA, we are adjusting those group means by another variable.

AgeOfStore is this new variable we will be introducing, and we want to create an ANCOVA model to see how the age of the restaurants in a certain promotional group impacts sales. The question we are asking when conducting our ANCOVA test is: does the mean restaurant sales still differ by marketing campaign when the age of restaurants is taken into account?

Both ANCOVA and ANOVA testing involve mean analysis; however, the means of the underlying populations are different. When we conduct an ANOVA test we are comparing non-adjusted group means, where as in and ANCOVA test we are comparing adjusted group means. When we conduct our ANOVA testing we will not take into account AgeOfStore when analyzing each marketing campaigns mean sales. However, when we conduct our ANCOVA test, we do take into account AgeOfStore, and adjust our means accordingly before analyzing marketing campaign mean sales variance. In other words, when we are conducting an ANCOVA test, we follow the same procedural steps of an ANOVA test just with adjusted underlying population means.



4. Report your results.

ANOVA Global \(F\)-Test

Test Question: Do new menu item sales means vary by marketing campaign?

Since we have three different promotions, we will start will start by doing an analysis of variance (ANOVA), global \(f\)-test. If there were only two promotional campaigns, we could simply do a pairwise \(t\)-test to see if the two groups differ from each other. Reasons are discussed above.


STEP 1: Set up the hypotheses and select the alpha level.

\(H_{0}: \mu_{promo-1} = \mu_{promo-2} = \mu_{promo-3}\text{ (All promotions result in the same amount of sales)}\)

\(H_{a}: \mu_{promo-1} \ne \mu_{promo-2} \text{ or } \mu_{promo-2} \ne \mu_{promo-3} \text{ or } \mu_{promo-1} \ne \mu_{promo-3}\text{ (Not all promotions result in the same amount of sales)}\)

\(\alpha = 0.05\)


STEP 2: Select the appropriate test-statistic, \(f\).

\(f = \frac{\text{Mean Squares Between}}{\text{Mean Squares Within}}\)


STEP 3: State the decision rule.

Use R to find \(F_{k-1, n-k, \alpha}\) associated with a right hand tail probability of \(\alpha = 0.05\).

qf(0.95, df1=k-1, df2=n-k)

Reject \(H_{0}: \mu_{promo-1} = \mu_{promo-2} = \mu_{promo-3}\) if either are True:

  1. \(f\ge F_{2, 546, 0.05} = 3.01\)
  2. \(p < 0.05\)


STEP 4: Compute the test statistic, \(f\), and associated p-value, \(p\) using aov().
# One-Way ANOVA
test_1 = aov(formula = SalesInThousands ~ Promotion, data = data); test_1
summary_test_1 = summary(test_1); summary_test_1

\(f = 21.95\)

\(p = 6.7*10^{-10} \sim 0\)


STEP 5: State your conclusion.

Because \(f = 21.95 > 3.01 = F_{2,546, 0.05}\), and \(p = 6.7*10^{-10} < 0.05 = \alpha\), we reject the\(H_{0}: \mu_{promo-1} = \mu_{promo-2} = \mu_{promo-3}\)

We have sufficient evidence that at the \(\alpha = 0.05\) level that there is a difference in mean sales between marketing campaigns.

To answer our test question, since the global \(f\)-test was significant, new menu items sales means do in fact vary by marketing campaign. We now want to look into the pairwise comparisons of the sales means for each promotion.



Tukey’s Pairwise \(t\)-Tests

Test Question: Between which marketing campaigns does our difference lie?

Our global f-test has determined that there is a difference in mean sales between marketing campaigns, so we will conduct multiple Tukey Pairwise t-tests to determine which marketing campaign’s mean sales differ.

The same Tukey’s pairwise t-testing procedure shown for the comparison of Promotion 1 and Promotion 2 mean sales will be used for comparing Promotion 2 and Promotion 3 mean sales, and Promotion 1 and Promotion 3 mean sales.


Promotion 1 - Promotion 2

STEP 1: Set up the hypotheses and select the alpha level.

\(H_{0}:\mu_{promo-1} = \mu_{promo-2}\)

\(H_{a}: \mu_{promo-1} \ne \mu_{promo-2}\)

\(\alpha = 0.05\)


STEP 2: Select the appropriate test-statistic, \(t\).

\(t = \frac{\bar{x}_{promo-1} - \bar{x}_{promo-2}}{\sqrt{s^{2}_{p}(\frac{1}{n_{promo-1}} + \frac{1}{n_{promo-2}})}}\)


STEP 3: State the decision rule.
qt(0.975, df = n-k)

Reject \(H_{0}:\mu_{promo-1} = \mu_{promo-2}\) if either are True:

  1. \(t \ge T_{n-k,\frac{\alpha}{2}} = 1.96\text{ or } t \le -T_{n-k,\frac{\alpha}{2}}= -1.96\)
  2. \(p < \frac{\alpha}{2} = 0.025 \text{ (Right hand tail probability)}\)
  3. \(0\) is not within the bounds of our confidence interval.


STEP 4: Compute the \(t\)-statistic, \(t\), confidence interval, and associated p-value, \(p\).
# Manual Calculation of t_value
t_value = (mean_1 - mean_2) / sqrt((std_1**2/n_1 + std_2**2/n_2)); t_value
# Welch t-test
t.test(promo_1$SalesInThousands, promo_2$SalesInThousands)

# Tukey Comparison of Means
TukeyHSD(test_1)
# Non-Adjusted p-values (will not use just for clarity)
pairwise.t.test(data$SalesInThousands, data$Promotion, p.adj="none")

\(t = 6.43\)

\(\text{Confidence Interval = (6.77, 14.8)}\)

\(p = 4.29*10^{-10} \sim 0\)


STEP 5: State your conclusion.

Because \(p = 4.29*10^{-10} < 0.025 = \frac{\alpha}{2}\), and \(t = 6.43 \ge 1.96 = T_{545,0.025}\), we reject the \(H_{0}:\mu_{promo-1} = \mu_{promo-2}\)

Using the Tukey Pairwise T-Test, we have sufficient evidence that at the \(\alpha = 0.05\) level that the mean sales of restaurants using Promotion 1, \(\mu_{promo-1} = 58.10\), and restaurants using Promotion 2, \(\mu_{promo-2} = 47.33\), are different from one another. The observed difference in mean sales between restaurants conducting Promotion 1 and restaurants conducting Promotion 2 was \(10.77\) thousand dollars.

We are 95% confident that the true difference between the sales means is between \(6.77\) and \(14.8\) thousand dollars. Another interpretation of our null hypothesis states that \(H_{0}:\mu_{promo-1} - \mu_{promo-2} = 0\), testing to see if the difference between the two means is zero. Since a difference of \(0\) is not in our confidence interval, we can again reject the \(H_{0}:\mu_{promo-1} = \mu_{promo-2}\).


Promotion 2 - Promotion 3

t_value = (mean_2 - mean_3) / sqrt((std_2**2/n_2 + std_3**2/n_3)); t_value
t.test(promo_3$SalesInThousands, promo_2$SalesInThousands)

Because \(p = 1.57*10^{-6} < 0.025 = \frac{\alpha}{2}\), and \(t = 4.88 \ge 1.96 = T_{545,0.025}\), we reject the \(H_{0}:\mu_{promo-2} = \mu_{promo-3}\)

Using the Tukey Pairwise T-Test, we have sufficient evidence that at the \(\alpha = 0.05\) level that the mean sales of restaurants using Promotion 2, \(\mu_{promo-2} = 47.33\), and restaurants using Promotion 3, \(\mu_{promo-3} = 55.36\), are different from one another. The observed difference in mean sales between restaurants conducting Promotion 2 and restaurants conducting Promotion 3 was \(-8.03\) thousand dollars.

We are 95% confident that the true difference between the sales means is between \(-4.12\) and \(-11.95\) thousand dollars. Another interpretation of our null hypothesis states that \(H_{0}:\mu_{promo-2} - \mu_{promo-3} = 0\), testing to see if the difference between the two means is zero. Since a difference of $0$ is not in our confidence interval, we can again reject the \(H_{0}:\mu_{promo-2} = \mu_{promo-3}\).


Promotion 1 - Promotion 3

t_value = (mean_1 - mean_3) / sqrt((std_1**2/n_1 + std_3**2/n_3)); t_value
t.test(promo_1$SalesInThousands, promo_3$SalesInThousands)

Because \(p = 0.24 > 0.025 = \frac{\alpha}{2}\), and \(t = 1.55 < 1.96 = T_{545,0.025}\), we fail to reject the \(H_{0}:\mu_{promo-1} = \mu_{promo-3}\)

Using the Tukey Pairwise T-Test, we have sufficient evidence that at the \(\alpha = 0.05\) level that the mean sales of restaurants using Promotion 1, \(\mu_{promo-1} = 58.10\), and restaurants using Promotion 3, \(\mu_{promo-3} = 55.36\), are different from one another. The observed difference in mean sales between restaurants conducting Promotion 1 and restaurants conducting Promotion 3 was \(-2.73\) thousand dollars.

We are 95% confident that the true difference between the sales means is between \(-1.26\) and \(6.74\) thousand dollars. Another interpretation of our null hypothesis states that \(H_{0}:\mu_{promo-1} - \mu_{promo-3} = 0\), testing to see if the difference between the two means is zero. Since a difference of \(0\) is in our confidence interval, we also fail to reject the \(H_{0}:\mu_{promo-1} = \mu_{promo-3}\).


ANCOVA

Test Question: Does the mean restaurant sales still differ by marketing campaign when the age of restaurants is taken into account?

Through our investigation of our data in Part 1, we have no reason to suspect a correlation between SalesInThousands, and AgeOfStore, MarketSize, or Week. However, for completeness, lets look at the AgeOfStore variable, and conduct a quick ANOVA test using R to confirm that it has no effect on the variance in mean sales between marketing campaigns.

# Interested in mean sales, Adjusting for Age
# ORDER MATTERS when you use aov()
ancova_model = aov(SalesInThousands ~ Promotion + AgeOfStore, data = data)
Anova(ancova_model, type="III")
Anova Table (Type III tests)

Response: SalesInThousands
            Sum Sq  Df   F value    Pr(>F)    
(Intercept) 400338   1 1535.1069 < 2.2e-16 ***
Promotion    11569   2   22.1816 5.487e-10 ***
AgeOfStore     245   1    0.9404    0.3326    
Residuals   141869 544                        
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Table 5.0: ANOVA Table for our ANCOVA Model that takes into account both marketing campaign (Promotion) and AgeOfStore.


We see in Table 5.0 that AgeOfStore is not significantly associated with the mean sales of a restaurant with a large \(p = 0.3326\), while the marketing campaign remains to be significantly associated with the mean sales with a small \(p = 5.49*10^{-10}\). Additionally, the \(f\)-statistic for the marketing campaign variable has not changed, remaining high at around \(22\).

Therefore, we do not have sufficient evidence at the \(\alpha = 0.05\) level that the difference in amount of sales between marketing campaigns is associated with the AgeOfStore. This means that the mean sales of each marketing campaign will not change significantly when we take into account AgeOfStore. Therefore, there is no need to look at the pairwise comparisons of the sales numbers for each promotion after adjusting for AgeOfStore.


5. State your conclusions and discuss any limitations.

Conclusions

We concluded that globally that their was a significant different between marketing campaigns mean sales. In the context of our question, this indicates that we need to figure out between which marketing campaigns the difference lies, so we can identify the specific marketing campaign that is generating the most sales.

Comparison \(t\)-statistic \(p_{tukey}\) value Conclusion
Promo 1 - Promo 2 6.43 0 Significant difference between means.
Promo 2 - Promo 3 4.88 0.0000055 Significant difference between means.
Promo 1 - Promo 3 1.55 0.24 Insignificant difference between means.

Table 6.0: Summary of Tukey’s Pairwise T-Test results.

When looking at the differences in mean sales between marketing campaigns, both Promotion 1 and Promotion 3 were significantly different that Promotion 2, but not significantly different from one another. Both Promotion 1 and Promotion 3 have higher means than Promotion 2, meaning these are the two campaigns that resulted in more new menu items sales than than the Promotion 2 marketing campaign. Both Promotion 1 and Promotion 3 mean sales figures were different from one another, but not significantly different at the \(\alpha = 0.05\) level. Therefore, either the Promotion 1 or Promotion 3 marketing campaign should be preferred over the Promotion 2 marketing campaign in order to increases the total sales of new menu items. To answer our research question, Promotion 1 and Promotion 3 marketing campaigns are most likely to result in the greatest increase in sales of new menu items for the restaurant chain.

TukeyHSD(test_1, conf.level = 0.99)

Even if we conduct a Tukey Pairwise T-Test at the \(\alpha = 0.01\) level, the results are the same, so the restaurant should feel confident moving forwards with either Promotion 1 or Promotion 3 marketing campaigns, and should consider looking into other marketing campaign factors, costs of the campaigns, ease of implementation, staying power, etc. to determine which of the two campaigns to implement across all restaurants.

Our ANCOVA testing adjusting for AgeOfStore showed no correlation between AgeOfStore and SalesInThousands means for each marketing campaign. Meaning, even when AgeOfStore was taken into account, we did not change our conclusion from our original ANOVA test, and maintain that at the \(\alpha = 0.05\) level, mean sales difference between for Promotion 1, Promotion 2, and Promotion 3 are associated with marketing campaign.

Lastly, we have a three topics we wanted to circle back upon after we tested our data. In regards to the 30 sales outliers found in the Promotion 2 subset discussed in our exploration of the data, these will have no impact on our final conclusions. These outliers all fall above the mean, and therefore drag the mean up, giving Promotion 2 an artificially large mean. If these outliers were removed, along with the outliers for the other marketing campaigns, the difference between Promotion 2 sales mean and the sales means of Promotion 1 and Promotion 3 would be even more significant. Therefore, we can disregard the effect of these outliers when making our conclusion.

After concluding mean sales for Promotion 2 to be significantly different from Promotion 2 and 3, we should give more credence to our discussion regarding Figure 6.0. And I would recommend that the restaurant chain investigate Promotion 2’s large market restaurants to understand why they may have under-performed. This may give clarity to some of the causes of the association we found between marketing campaign and mean sales.

Finally, our data did not follow the ANOVA rule of thumb that if the between group variance is small and the within group variance is large then it is likely that the underlying means are all equal. Despite this, we did find the underlying means were not all equal, and there was significant difference between underlying population means. This shows the important of testing, doing the actual math (thank you R), even when the data is visually communicating a seemingly clear conclusion.


Assumptions

In order to make inferences using ANOVA methodology, we have to make sure three conditions are met:

  1. Independent, random samples from each group in the population.

Our data source stated that each restaurant in the marketing study was chosen at random from all of the companies restaurants. Furthermore, the marketing campaign assigned to each restaurant was also chosen at random. Each restaurant was only tested once, for one marketing campaign over one month. Assumption 1 is therefore met.

  1. Outcome of interest in group/population is normally distributed with unknown mean
  2. Outcome of interest in each group/population has a similar unknown standard deviation

Lets graphs some histograms of our outcome of interest, SalesInThousands, for each group, Promotion, in order to check for normality and variance similarity.

# Distributions
## Promotion 1 (Code for Promotion 2 and 3 are identical, but hidden)
breaks = seq(from = 20, to = 100, by=2)

promo_1_hist = ggplot(promo_1, aes(x=SalesInThousands)) + 
  geom_histogram(aes(y = ..density..), breaks = breaks, color='gray80', fill="gray80") + 
  ggtitle('Promotion 1 Sales Density Histrogram') +
  xlab("Sales (in thousands)") +
  ylab("Density") + 
  geom_density(color = "black", fill=colors_4[1],  alpha=0.5) + 
  geom_vline(xintercept = mean(promo_1$SalesInThousands), linetype="dashed", color='darkblue', size = 0.8) +
  annotate("text",color='darkblue', size = 3, x=mean(promo_1$SalesInThousands)+1.25, y=0.0075, 
          label= paste("Mean Sales =", round(mean(promo_1$SalesInThousands), 2)), angle=90) +
  theme(panel.grid.major = element_line(color="gray90"), panel.grid.minor = element_line(color="gray94"),
        panel.background = element_blank(), axis.line = element_line(colour = "gray90", size =0.5)) +
  theme(panel.border = element_rect(fill=NA, colour = "gray90",
                                    size = 0.5, linetype = "solid")) +
  theme(axis.ticks = element_line(color="gray90", size=0.5)) +
  theme(axis.ticks.length = unit(0.18, "cm")) +
  theme(axis.line = element_line(colour = "gray90",
                                 size = 0.5, linetype = "solid")) +
  theme(axis.text.x = element_text(face="plain", color="black",
                                   size=8, angle=0),
        axis.text.y = element_text(face="plain", color="black",
                                   size=8, angle=0)) +
  theme(axis.title = element_text(face="plain", color="black",
                                  size=12, angle=0)) +
  theme(plot.title = element_text(face="plain", color="black",
                                  size=14, angle=0)) 
# promo_1_hist

Figure 10.0: Sales histograms for restaurants using Promotion 1 (purple), Promotion 2 (blue), and Promotion 3 (green).


All three density histograms are in the same scale, making it easy for us to compare both normality and variance. When we explored the data in Part 1, the data for each sub population (Promotion 1, Promotion 2 and Promotion 3) had very similar distributions (see Table 2.0). Our density histograms in Figure 10.0 confirm that similarity.

All three marketing campaigns distributions are extremely symmetric. Although none of the histograms are perfectly normal, which is expected as perfect normality is rare in practice, they are somewhat normal. All histograms have one major peak around \(53\) thousand dollars, and a second minor peak at around \(80\) thousand dollars. All histograms skew right which is expected for most monetary distributions. The deviation from normality is not severe enough to warrant concern for a couple reasons. Firstly, ANOVA testing is very robust especially when we are using a large sample size of \(588\) restaurants. Secondly, the deviations from normality are similar between the underlying populations.

All three marketing campaigns show very similar variance for SalesInThousands at around \(16.75\). Visually, all three distributions look very similar in width, indicating similar variance among the three marketing campaigns sales. According to the Central Limit Theorem, as our sample size increases, our variance decreases. Because each marketing campaign population has around \(170\) restaurants each, our symmetric variance can be partly attributed to the rather large, equally proportioned underlying population sizes. If we had one underlying population with a disproportionately small population size, say Promotion 1 had \(30\) restaurants instead of \(172\), we would likely see a variance that was not similar to the other underlying populations. Luckily this is not the case. The general rule of thumb used in practice to check for variance similarity is that the largest sample standard deviation should be no more than twice as large as the smallest sample standard deviation. Our data follows this rule.

In conclusion, both all three assumptions are met.


Limitations

From our exploration of the data, the only variable with association to a restaurant’s SalesInThousands was the marketing campaigned used, AgeOfStore was shown to have no correlation in our ANCOVA test and when we did a simple correlation coefficient calculation. However, There may be lurking variables that have a strong influence on a restaurant’s SalesInThousands that were not measured by the company in our study. Although SalesInThousands and Promotion are associated, it is highly likely that the marketing campaign is not the only variable that is responsible for differences in sales figures.

For example, maybe the lower sales observed in was due to that underlying population having more restaurants in poorer areas with people who cannot afford to eat out, or maybe affluent area that don’t eat at the restaurant often. To continue, maybe the market demographics of the underlying populations are different. If Promotion 2 was a digital marketing campaign and the Promotion 2’s market demographics skewed older than the Promotion 1 and Promotion 2 markets, that demographic difference may have caused the decrease in the effectiveness of the marketing campaign, not the campaign itself. There are many lurking variables, and near impossible to account for all of them.

If time and capital were inconsequential, one way in which the company could vet our conclusions would be to switch the marketing campaigns each restaurant cohort uses and regather sales data. For instance, all restaurants that used Promotion 1 will use Promotion 2, Promotion 2 will use Promotion 3, and Promotion 3 will use Promotion 1. If our conclusion that Promotion 2 marketing campaign was least effective at increasing sale holds, we would be more confidence in the effect of the marketing campaign on sales. Even though this may answer some of our questions about demographic differences discussed above, we can never account for every lurking variable, and we can never be fully certain about causation, only strength of association. We would need to design and conduct many more studies to suggest causation.




LS0tCnRpdGxlOiAiUmVzdGF1cmFudCBNYXJrZXRpbmcgQ2FtcGFpZ24gQS9CIFRlc3RpbmciCmF1dGhvcjogIkNvZHkgVGhheWVyICB8IERlY2VtYmVyIDE0LCAyMDIyIgpzdWJ0aXRsZTogIkNTNTU1IEZpbmFsIFByb2plY3QgKFByb2YuIEFsaXphZGVoLVNoYWJkaXosIEZhbGwgMjAyMikiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCjxici8+CgojIyMgUHJvamVjdCBGaWxlcwoKPiAqKkhUTUwgZmlsZSoqIGlzIHRoZSBtb3N0IHJlYWRhYmxlIGFuZCBoYXMgaW50cmFjdGFibGUgZ3JhcGhzLCBidXQgdGhlIHNvdXJjZSBjb2RlIG9mIGFsbCB0aGUgZmlndXJlcyBpcyBoaWRkZW4gZm9yIGNsYXJpdHkuCj4KPiAqKlJNRCBmaWxlKiogY29udGFpbnMgYWxsIHRoZSBzb3VyY2UgY29kZS4KPgo+ICoqUERGIGZpbGUqKiBpcyBqdXN0IGEgcGRmIHZlcnNpb24gb2YgdGhlIFJNRCBmaWxlLgoKYGBge3IgcmVzdWx0cz0iaGlkZSJ9CmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSkKYGBgCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeSh2aXJpZGlzKQpsaWJyYXJ5KGVtbWVhbnMpCmxpYnJhcnkoY2FyKQoKCiMgQ29sb3JzCmNvbG9yc18zID0gYyh2aXJpZGlzKDI1KVs0XSwgdmlyaWRpcygyNSlbMTBdLCB2aXJpZGlzKDI1KVsxNV0sIHZpcmlkaXMoMjUpWzE5XSkKY29sb3JzXzQgPSBjKHZpcmlkaXMoMjUpWzFdLCB2aXJpZGlzKDI1KVs0XSwgdmlyaWRpcygyNSlbMTBdLCB2aXJpZGlzKDI1KVsxNV0sIHZpcmlkaXMoMjUpWzE5XSkKYGBgCgo8YnIvPgoKIyMgMS4gRGVzY3JpYmUgeW91ciByZXNlYXJjaCBzY2VuYXJpbyBhbmQgcXVlc3Rpb25zKHMpLgoKPGJyLz4KCkEgcmVzdGF1cmFudCBjaGFpbiBpcyBjaGFuZ2luZyBpdHMgbWVudSBieSBhZGRpbmcgYSBmZXcgbmV3IGl0ZW1zLiBUaGUgcmVzdGF1cmFudCB3YW50eCB0byB0ZXN0IHRocmVlIGRpZmZlcmVudCBtYXJrZXRpbmcgY2FtcGFpZ25zIHRoZXkgYXJlIHRoaW5raW5nIGFib3V0IHVzaW5nIHRvIHByb21vdGUgdGhlaXIgbmV3IG1lbnUgaXRlbXMuIFRoZSByZXN0YXVyYW50IHdhbnRzIHRvIGRldGVybWluZSB3aGljaCBwcm9tb3Rpb24gaGFzIHRoZSBncmVhdGVzdCBlZmZlY3Qgb24gc2FsZXMgb2YgbmV3IG1lbnUgaXRlbXMuIFRoZSByZXN0YXVyYW50IGxvY2F0aW9ucyBpbiB3aGljaCB0aGUgY2FtcGFpZ25zIHdpbGwgYmUgdGVzdGVkIGFyZSBzZWxlY3RlZCBhdCByYW5kb20uIEVhY2ggcmFuZG9tbHkgc2VsZWN0ZWQgbG9jYXRpb24gd2lsbCBiZWdpbiBzZXJ2aW5nIHRoZSBuZXcgbWVudSBpdGVtcywgYW5kIHJ1biBvbmUgb2YgdGhlIHRocmVlIG1hcmtldGluZyBjYW1wYWlnbnMsIGFsc28gY2hvc2VuIGF0IHJhbmRvbS4gVGhlIHdlZWtseSBzYWxlcyBvZiB0aGUgbmV3IG1lbnUgaXRlbXMgYXJlIHJlY29yZGVkIGZvciB0aGUgZmlyc3QgZm91ciB3ZWVrcyBvZiB0aGUgbWFya2V0aW5nIGNhbXBhaWduLgoKVGhlIHJlc3RhdXJhbnQgY2hhaW4gaXMgaGlyaW5nIGEgZGF0YSBzY2llbnRpc3QgdG8gZXZhbHVhdGUgdGhlIGVmZmVjdGl2ZW5lc3Mgb2YgdGhyZWUgZGlmZmVyZW50IG1hcmtldGluZyBjYW1wYWlnbnMuIFRoZSByZXN0YXVyYW50IHdhbnRzIHRvIGRldGVybWluZSB3aGljaCBvZiB0aGUgdGhyZWUgbWFya2V0aW5nIHN0cmF0ZWdpZXMgaXMgbW9zdCBlZmZlY3RpdmUgYXQgaW5jcmVhc2luZyBzYWxlcyBvZiBuZXcgbWVudSBpdGVtcywgc28gdGhleSBjYW4gY29uZmlkZW50bHkgaW1wbGVtZW50IHNhaWQgbWFya2V0aW5nIGNhbXBhaWduIGF0IGFsbCB0aGVpciByZXN0YXVyYW50IGxvY2F0aW9ucy4KCioqUmVzZWFyY2ggUXVlc3Rpb246KiogV2hpY2ggbWFya2V0aW5nIGNhbXBhaWduKHMpIHJlc3VsdHMgaW4gdGhlIGdyZWF0ZXN0IGluY3JlYXNlIGluIHNhbGVzIG9mIG5ldyBtZW51IGl0ZW1zIGZvciB0aGUgcmVzdGF1cmFudCBjaGFpbj8KCk1hbnkgYXV4aWxsYXJ5IHF1ZXN0aW9ucyB3aWxsIGJlIGFuc3dlcmVkIGluIG91ciBqb3VybmV5IHRvIGFuc3dlciB0aGUgYWJvdmUgcXVlc3Rpb24sIGJ1dCB0aGUgYWJvdmUgcXVlc3Rpb24gaXMgdGhlIGNvcmUsIGd1aWRpbmcgaW5xdWlyeSBvZiBvdXIgaW52ZXN0aWdhdGlvbi4KCjxici8+PGJyLz4KCiMjIDIuIERlc2NyaWJlIHRoZSBkYXRhIHNldC4gey50YWJzZXR9CgoqKkRhdGEgU291cmNlOioqIDxodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL2NoZWJvdGluYWEvZmFzdC1mb29kLW1hcmtldGluZy1jYW1wYWlnbi1hYi10ZXN0P3Jlc291cmNlPWRvd25sb2FkPgoKYGBge3J9CiMgSW5wdXQgRGF0YSBmcm9tIGNzdiBmaWxlLgpkYXRhID0gcmVhZC5jc3YoZmlsZSA9ICJXQV9NYXJrZXRpbmctQ2FtcGFpZ24uY3N2IiwgaGVhZGVyID0gVFJVRSk7IGRhdGEKCiMgRmFjdG9yIHRoZSBEYXRhIHRvIG1ha2UgaXQgZWFzaWVyIHRvIHdvcmsgd2l0aC4KZGF0YSRQcm9tb3Rpb24gPSBmYWN0b3IoZGF0YSRQcm9tb3Rpb24pOyBkYXRhJFByb21vdGlvbgpsZXZlbHMoZGF0YSRQcm9tb3Rpb24pCmRhdGEkd2VlayA9IGZhY3RvcihkYXRhJHdlZWspCmxldmVscyhkYXRhJHdlZWspCnRpYmJsZShkYXRhKQoKIyBDcmVhdGUgU3Vic2V0cyBmb3IgZWFjaCBNYXJrZXRpbmcgQ2FtcGFpZ24gdG8gbWFrZSBvdXIgbGlmZSBlYXNpZXIuCnByb21vXzEgPSBmaWx0ZXIoZGF0YSwgUHJvbW90aW9uID09IDEpOyBwcm9tb18xCnByb21vXzIgPSBmaWx0ZXIoZGF0YSwgUHJvbW90aW9uID09IDIpOyBwcm9tb18yCnByb21vXzMgPSBmaWx0ZXIoZGF0YSwgUHJvbW90aW9uID09IDMpOyBwcm9tb18zCgojIERhdGEgd2FzIGx1Y2tpbHkgdmVyeSBjbGVhbiwgbm90IGEgbG90IG9mIGRhdGEgY2xlYW5pbmcgd2FzIG5lY2Vzc2FyeS4KYGBgCgpgYGB7cn0KcHJpbnQoZGF0YSkKYGBgCgo8YnIvPgoKfCAgICAgICAgICAgICAgICAgICAgICAgIHwgRGVzY3JpcHRpb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBWYWx1ZXMgICAgICAgICAgICAgICAgfAp8Oi0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLXwKfCAqKipNYXJrZXRJRCoqKiAgICAgICAgIHwgVW5pcXVlIGlkZW50aWZpZXIgZm9yIG1hcmtldC4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBSYW5nZSgxOjEwKSAgICAgICAgICAgfAp8ICoqKk1hcmtldFNpemUqKiogICAgICAgfCBTaXplIG9mIG1hcmtldCBhcmVhIGJ5IHNhbGVzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFNtYWxsLCBNZWRpdW0sIExhcmdlLiB8CnwgKioqTG9jYXRpb25JRCoqKiAgICAgICB8IFVuaXF1ZSBpZGVudGlmaWVyIGZvciBzdG9yZSBsb2NhdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgIHwKfCAqKipBZ2VPZlN0b3JlKioqICAgICAgIHwgQWdlIG9mIHN0b3JlIGluIHllYXJzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgICAgfAp8ICoqKlByb21vdGlvbioqKiAgICAgICAgfCBPbmUgb2YgdGhyZWUgcHJvbW90aW9ucyB0aGF0IHdlcmUgdGVzdGVkICAgICAgICAgICAgICAgICAgICAgICAgICB8IFJhbmdlKDE6MykgICAgICAgICAgICB8CnwgKioqd2VlayoqKiAgICAgICAgICAgICB8IE9uZSBvZiBmb3VyIHdlZWtzIHdoZW4gdGhlIHByb21vdGlvbnMgd2VyZSBydW4gICAgICAgICAgICAgICAgICAgIHwgUmFuZ2UoMTo0KSAgICAgICAgICAgIHwKfCAqKipTYWxlc0luVGhvdXNhbmRzKioqIHwgU2FsZXMgYW1vdW50IGZvciBhIHNwZWNpZmljICpMb2NhdGlvbklEKiwgKlByb21vdGlvbiosIGFuZCAqd2VlayogfCAgICAgICAgICAgICAgICAgICAgICAgfAoKPGJyLz4KCiMjIyAqKlNhbGVzSW5UaG91c2FuZHMqKgoKTGV0cyBmaXJzdCBsb29rIGF0IHRoZSAqKipTYWxlc0luVGhvdXNhbmRzKioqIHZhcmlhYmxlIGZvciBlYWNoIG9mIHRoZSB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zLiBUaGUgKioqU2FsZXNJblRob3VzYW5kcyoqKiB2YXJpYWJsZSBpcyB0aGUgc2FsZXMgYW1vdW50IGluIHRob3VzYW5kcyBvZiBuZXcgbWVudSBpdGVtcyBmb3IgYSBzcGVjaWZpYyByZXN0YXVyYW50LgoKKipFeHBsb3JhdG9yeSBRdWVzdGlvbjoqKiBBcmUgdGhlIHNhbGVzIG9mIG5ldyBtZW51IGl0ZW1zIHNpbWlsYXIgZm9yIGVhY2ggbWFya2V0aW5nIGNhbXBhaWduIGdyb3VwPwoKYGBge3J9CiMgU3VtbWFyeSBTdGF0aXN0aWNzCiMgTWVhbgptZWFuXzEgPSBtZWFuKHByb21vXzEkU2FsZXNJblRob3VzYW5kcyk7IG1lYW5fMQptZWFuXzIgPSBtZWFuKHByb21vXzIkU2FsZXNJblRob3VzYW5kcyk7IG1lYW5fMgptZWFuXzMgPSBtZWFuKHByb21vXzMkU2FsZXNJblRob3VzYW5kcyk7IG1lYW5fMwptZWFuX3RvdCA9IG1lYW4oZGF0YSRTYWxlc0luVGhvdXNhbmRzKTsgbWVhbl90b3QKCiMgU3RhbmRhcmQgRGV2aWF0aW9uCnN0ZF8xID0gc2QocHJvbW9fMSRTYWxlc0luVGhvdXNhbmRzKTsgc3RkXzEKc3RkXzIgPSBzZChwcm9tb18yJFNhbGVzSW5UaG91c2FuZHMpOyBzdGRfMgpzdGRfMyA9IHNkKHByb21vXzMkU2FsZXNJblRob3VzYW5kcyk7IHN0ZF8zCnN0ZF90b3QgPSBzZChkYXRhJFNhbGVzSW5UaG91c2FuZHMpOyBzdGRfdG90CgojIE51bWJlciBvZiBTYW1wbGVzCm4gPSBucm93KGRhdGEpOyBuCmsgPSBsZW5ndGgobGV2ZWxzKGRhdGEkUHJvbW90aW9uKSkKbl8xID0gbnJvdyhwcm9tb18xKTsgbl8xCm5fMiA9IG5yb3cocHJvbW9fMik7IG5fMgpuXzMgPSBucm93KHByb21vXzMpOyBuXzMKYGBgCgp8IE1hcmtldGluZyBDYW1wYWlnbiB8IFNhbGVzIChJbiBUaG91c2FuZHMpIHwgU3RhbmRhcmQgRGV2aWF0aW9uIHwgUG9wdWxhdGlvbiB8Cnw6LS0tLS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tOnwKfCAgICAgIFByb21vIDEgICAgICAgfCAgICAgICAgNTguMTAgICAgICAgICB8ICAgICAgIDE2LjU1ICAgICAgICB8ICAgIDE3MiAgICAgfAp8ICAgICAgUHJvbW8gMiAgICAgICB8ICAgICAgICA0Ny4zMyAgICAgICAgIHwgICAgICAgMTUuMTEgICAgICAgIHwgICAgMTg4ICAgICB8CnwgICAgICBQcm9tbyAzICAgICAgIHwgICAgICAgIDU1LjM2ICAgICAgICAgfCAgICAgICAxNi43NyAgICAgICAgfCAgICAxODggICAgIHwKfCAgICAgKipUb3RhbCoqICAgICAgfCAgICAgICAgNTMuNDcgICAgICAgICB8ICAgICAgIDE2Ljc1ICAgICAgICB8ICAgIDU0OCAgICAgfAoKKioqVGFibGUgMS4wOioqIFN1bW1hcnkgc3RhdGlzdGljcyBmb3Igc2FsZXMgb2YgbmV3IG1lbnUgaXRlbXMgZm9yIGFsbCByZXN0YXVyYW50cyBwYXJ0aWNpcGF0aW5nIGluIHRoZSBuZXcgbWFya2V0aW5nIGNhbXBhaWducy4qCgo8YnIvPgoKVGhlIHRocmVlIGRpZmZlcmVudCBtYXJrZXRpbmcgY2FtcGFpZ25zIHN1YnNldHMgKFByb21vdGlvbiAxLCBQcm9tb3Rpb24gMiwgYW5kIFByb21vdGlvbiAzKSBoYXZlIHZlcnkgc3ltbWV0cmljIGRhdGEsIGFsbCBoYXZpbmcgc2ltaWxhciBtZWFucywgc3RhbmRhcmQgZGV2aWF0aW9ucyBhbmQgcG9wdWxhdGlvbiBzaXplcyBzZWVuIGluICoqVGFibGUgMS4wKiouIExldHMgY3JlYXRlIGEgYm94cGxvdCB0byB2aXN1YWxpemUgdGhpcyBzeW1tZXRyeS4KCmBgYHtyfQojIFNhbGVzIEJveHBsb3QKZGF0YV8yID0gZGF0YQpkYXRhXzIkUHJvbW90aW9uID0gYXMuY2hhcmFjdGVyKGRhdGFfMiRQcm9tb3Rpb24pCgpzYWxlc19wcm9tb19ib3ggPSBnZ3Bsb3QoZGF0YV8yLCBhZXMoeD1Qcm9tb3Rpb24sIHk9U2FsZXNJblRob3VzYW5kcywgZmlsbD1Qcm9tb3Rpb24pKSArIAogIHlsYWIoIlNhbGVzIChpbiB0aG91c2FuZHMpIikgKwogIHhsYWIoIk1hcmtldGluZyBDYW1wYWlnbiIpICsKICBnZW9tX2JveHBsb3QoKSArIGNvb3JkX2ZsaXAoKSArIAogIGdlb21fYm94cGxvdChjb2xvcj0iYmxhY2siKSArIAogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkgKwogIGdlb21fcG9pbnQoc2hhcGU9MTYsIHBvc2l0aW9uPXBvc2l0aW9uX2ppdHRlcigwLjEpLCBjb2xvdXI9ImJsYWNrIiwgYWxwaGE9LjUwKSArCiAgICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yPSJncmF5OTAiKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvcj0iZ3JheTk0IiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5OTAiLCBzaXplID0wLjUpKSArCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGw9TkEsIGNvbG91ciA9ICJncmF5OTAiLCBzaXplID0gMC41LCBsaW5ldHlwZSA9ICJzb2xpZCIpKSArIAogIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyYXk5MCIsIHNpemU9MC41KSkgKyAKICB0aGVtZShheGlzLnRpY2tzLmxlbmd0aCA9IHVuaXQoMC4xOCwgImNtIikpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCnNhbGVzX3Byb21vX2JveApgYGAKCioqKkZpZ3VyZSAxLjA6KiogQm94IHBsb3Qgc2hvd2luZyB0aGUgZGlmZmVyZW5jZSBpbiByZXN0YXVyYW50IHNhbGVzIGRhdGEgZm9yIGVhY2ggb2YgdGhlIHRocmVlIG1hcmtldGluZyBjYW1wYWlnbnMuIFByb21vdGlvbiAxIGlzIGluIHB1cnBsZSwgUHJvbW90aW9uIDIgaXMgaW4gZ3JlZW4sIGFuZCBQcm9tb3Rpb24gMyBpcyBpbiB5ZWxsb3cuKgoKPGJyLz4KClByb21vdGlvbiAxIGhhcyB0aGUgaGlnaGVzdCBtZWFuIHNhbGVzIG9mIG5ldyBtZW51IGl0ZW1zLCBmb2xsb3dlZCBieSBQcm9tb3Rpb24gMyBhbmQgdGhlbiBQcm9tb3Rpb24gMi4gQWxsIGhhdmUgc2ltaWxhciB2YXJpYW5jZSwgd2hpY2ggaXMgaW1wb3J0YW50IHdoZW4gY29tcGFyaW5nIG1lYW5zLiBIb3dldmVyLCB0aGVyZSBzZWVtcyB0byBiZSBtb3JlIFByb21vdGlvbiAyIG91dGxpZXJzLiBMZXRzIHNlZSBpZiB0aGF0IGlzIHRydWUuCgpgYGB7cn0KIyBJZGVudGlmeSBPdXRsaWVycyB1c2luZyBJUVIgTWV0aG9sb2d5CgpJUVIgPSBzdW1tYXJ5KHByb21vXzEkU2FsZXNJblRob3VzYW5kcylbNV0gLSBzdW1tYXJ5KHByb21vXzEkU2FsZXNJblRob3VzYW5kcylbMl07IElRUgpvdXRsaWVycyA9IGZpbHRlcihwcm9tb18xLCBTYWxlc0luVGhvdXNhbmRzID4gc3VtbWFyeShwcm9tb18xJFNhbGVzSW5UaG91c2FuZHMpWzVdICsgKDEuNSAqIElRUikgfCBTYWxlc0luVGhvdXNhbmRzIDwgc3VtbWFyeShwcm9tb18xJFNhbGVzSW5UaG91c2FuZHMpWzNdIC0gKDEuNSAqIElRUikpOyBvdXRsaWVycyRTYWxlc0luVGhvdXNhbmRzCgpJUVIgPSBzdW1tYXJ5KHByb21vXzIkU2FsZXNJblRob3VzYW5kcylbNV0gLSBzdW1tYXJ5KHByb21vXzIkU2FsZXNJblRob3VzYW5kcylbMl07IElRUgpvdXRsaWVyc18yID0gZmlsdGVyKHByb21vXzIsIFNhbGVzSW5UaG91c2FuZHMgPiBzdW1tYXJ5KHByb21vXzIkU2FsZXNJblRob3VzYW5kcylbNV0gKyAoMS41ICogSVFSKSB8IFNhbGVzSW5UaG91c2FuZHMgPCBzdW1tYXJ5KHByb21vXzIkU2FsZXNJblRob3VzYW5kcylbM10gLSAoMS41ICogSVFSKSk7IG91dGxpZXJzXzIkU2FsZXNJblRob3VzYW5kcwoKSVFSID0gc3VtbWFyeShwcm9tb18zJFNhbGVzSW5UaG91c2FuZHMpWzVdIC0gc3VtbWFyeShwcm9tb18zJFNhbGVzSW5UaG91c2FuZHMpWzJdOyBJUVIKb3V0bGllcnNfMyA9IGZpbHRlcihwcm9tb18zLCBTYWxlc0luVGhvdXNhbmRzID4gc3VtbWFyeShwcm9tb18zJFNhbGVzSW5UaG91c2FuZHMpWzVdICsgKDEuNSAqIElRUikgfCBTYWxlc0luVGhvdXNhbmRzIDwgc3VtbWFyeShwcm9tb18zJFNhbGVzSW5UaG91c2FuZHMpWzNdIC0gKDEuNSAqIElRUikpOyBvdXRsaWVyc18zJFNhbGVzSW5UaG91c2FuZHMKCm5yb3cob3V0bGllcnMpCm5yb3cob3V0bGllcnNfMikKbnJvdyhvdXRsaWVyc18zKQpgYGAKClVzaW5nIHRoZSBJUVIgbWV0aG9kb2xvZ3kgdG8gaWRlbnRpdHkgb3V0bGllcnMsIHdlIG9ic2VydmVkIDEyIHNhbGVzIG91dGxpZXJzIGVhY2ggZm9yIGJvdGggUHJvbW90aW9uIDEgYW5kIDIsIGFuZCAzMCBzYWxlcyBvdXRsaWVycyBmb3IgUHJvbW90aW9uIDMuIFRoaXMgaXMgYW4gaW1iYWxhbmNlIHdlIHNob3VsZCBrZWVwIGluIG1pbmQgYW5kIGNpcmNsZSBiYWNrIHRvIGJlZm9yZSB3ZSBtYWtlIGFueSBmaW5hbCBjb25jbHVzaW9ucyBhYm91dCBvdXIgZGF0YS4KClRvIGFuc3dlciBvdXIgZXhwbG9yYXRvcnkgcXVlc3Rpb24sICoqdGhlIHNhbGVzIG9mIG5ldyBtZW51IGl0ZW1zIHdlcmUgaW4gZmFjdCBzaW1pbGFyIGZvciBlYWNoIG1hcmtldGluZyBjYW1wYWlnbiBncm91cCBidXQgbm90IHRoZSBzYW1lLioqIFByb21vdGlvbiAyIGxvb2tzIHRvIGRldmlhdGUgZnJvbSBQcm9tb3Rpb24gMSBhbmQgUHJvbW90aW9uIDIsIGFuZCB3ZSB3aWxsIHRlc3QgdG8gc2VlIGlmIHRoYXQgZGV2aWF0aW9uIGlzIHNpZ25pZmljYW50LgoKPGJyLz4KCiMjIyAqKkFnZU9mU3RvcmUqKgoKTGV0cyBuZXh0IGxvb2sgYXQgdGhlICoqKkFnZU9mU3RvcmUqKiogdmFyaWFibGUgZm9yIGVhY2ggb2YgdGhlIHRocmVlIG1hcmtldGluZyBjYW1wYWlnbnMuIFRoZSAqKipBZ2VPZlN0b3JlKioqIHZhcmlhYmxlIGlzIGFnZSBvZiBlYWNoIHJlc3RhdXJhbnQgaW4gdGhlIHN0dWR5LgoKKipFeHBsb3JhdG9yeSBRdWVzdGlvbjoqKiBBcmUgYWdlIG9mIHJlc3RhdXJhbnQgZGlzdHJpYnV0ZWQgZGlmZmVyZW50IGluIGVhY2ggbWFya2V0aW5nIGNhbXBhaWduIGdyb3VwPwoKYGBge3IgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQoKIyBTY2F0dGVyIFBsb3QgQWdlIHZzLiBTYWxlcwp4ID0gZGF0YSRTYWxlc0luVGhvdXNhbmRzCnkgPSBkYXRhJEFnZU9mU3RvcmUKCmFnZV9zYWxlc19zY2F0dGVyID0gcGxvdF9seShkYXRhLCB5ID0gflNhbGVzSW5UaG91c2FuZHMsIHggPSB+QWdlT2ZTdG9yZSwgY29sb3IgPSB+UHJvbW90aW9uLCBjb2xvcnMgPSBjb2xvcnNfMywKICAgICAgICB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ21hcmtlcnMnLAogICAgICAgIG1hcmtlciA9IGxpc3Qoc3ltYm9sID0gJ2NpcmNsZScsIHNpemVtb2RlID0gJ2RpYW1ldGVyJywKICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KHdpZHRoID0gMSwgY29sb3IgPSAnYmxhY2snKSkpICU+JQpsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0FnZSBvZiBSZXN0YXVyYW50JywKICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGMobWluKHgpIC0gbWVhbih4KS9ucm93KHgpLCBtYXgoeCkgKyBtZWFuKHgpL25yb3coeCkpLAogICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLAogICAgICAgICAgICAgICAgICAgIHRpY2t3aWR0aCA9IDEuNSwKICAgICAgICAgICAgICAgICAgICB0aWNrbGVuID0gNSwKICAgICAgICAgICAgICAgICAgICB0aWNrcHJlZml4PSIiLAogICAgICAgICAgICAgICAgICAgIGdyaWR3aWR0aCA9IDEpLAogICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1NhbGVzIChpbiB0aG91c2FuZHMpJywKICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGMobWluKHkpIC0gbWVhbih5KS9ucm93KHkpLCBtYXgoeSkpICsgbWVhbih5KS9ucm93KHkpLAogICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLAogICAgICAgICAgICAgICAgICAgIHRpY2t3aWR0aCA9IDEuNSwKICAgICAgICAgICAgICAgICAgICB0aWNrbGVuID0gNSwKICAgICAgICAgICAgICAgICAgICBncmlkd2l0aCA9IDEpKQoKYWdlX3NhbGVzX3NjYXR0ZXIKYGBgCgoqKipGaWd1cmUgMi4wOioqIFNjYXR0ZXIgcGxvdCBzaG93aW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAqKkFnZU9mU3RvcmUqKiAoeCkgYW5kICoqU2FsZXNJblRob3VzYW5kcyoqICh5KSBmb3IgYWxsIHJlc3RhdXJhbnRzIGNvbmR1Y3RpbmcgbWFya2V0aW5nIGNhbXBhaWducyBmb3IgbmV3IG1lbnUgaXRlbXMuIERvdWJsZS1jbGljayBvbiB0aGUgbGVnZW5kIHRvIHZpZXcgaW5kaXZpZHVhbCBtYXJrZXRpbmcgY2FtcGFpZ25zLioKCjxici8+CgpMb29raW5nIGF0IHRoZSBzY2F0dGVyIHBsb3Qgb2YgYWdlIGFuZCBzYWxlcyBmb3IgcmVzdGF1cmFudHMgd2Ugb2JzZXJ2ZSBubyBjbGVhciBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHR3byB2YXJpYWJsZXMuIFdlIGNhbiBjb25maXJtIHRoaXMgd2l0aCBhIGNhbGN1bGF0aW9uIG9mIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCwgJHIkLgoKYGBge3J9CiMgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQKY29yKHg9ZGF0YSRBZ2VPZlN0b3JlLCB5PWRhdGEkU2FsZXNJblRob3VzYW5kcykKYGBgCgpPdXIgdGhlIGNhbGN1bGF0ZWQgY29ycmVsYXRpb24gY29lZmZpY2llbnQsICRyJCwgb2Ygc3RvcmUgYWdlIGFuZCBzdG9yZSBzYWxlcyBpcyAkLTAuMDI5JCwgd2hpY2ggaXMgYWxtb3N0IHplcm8sIG1lYW5pbmcgdGhlcmUgaXMgbGl0dGxlIHRvIG5vIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcy4KCmBgYHtyfQojIEFnZSBTdW1tYXJ5IFN0YXRpc3RpYwp0YXBwbHkoZGF0YSRBZ2VPZlN0b3JlLCBkYXRhJFByb21vdGlvbiwgc3VtbWFyeSkKCnN1bW1hcnkocHJvbW9fMSRBZ2VPZlN0b3JlKQpzZChwcm9tb18xJEFnZU9mU3RvcmUpCnN1bW1hcnkocHJvbW9fMiRBZ2VPZlN0b3JlKQpzZChwcm9tb18yJEFnZU9mU3RvcmUpCnN1bW1hcnkocHJvbW9fMyRBZ2VPZlN0b3JlKQpzZChwcm9tb18zJEFnZU9mU3RvcmUpCmBgYAoKfCAgICAgICAgICAgICAgICAgICAgICAgIHwgKipQcm9tbyAxKiogfCAqKlByb21vIDIqKiB8ICoqUHJvbW8gMyoqIHwKfDotLS0tLS0tLS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tOnwKfCAgICAgICAgKipNZWFuKiogICAgICAgIHwgICAgOC4yOCAgICAgfCAgICA3Ljk4ICAgICB8ICAgIDkuMjMgICAgIHwKfCAgICAgICAqKk1lZGlhbioqICAgICAgIHwgICAgICA2ICAgICAgfCAgICAgIDcgICAgICB8ICAgICAgOCAgICAgIHwKfCAqKlN0YW5kYXJkIERldmlhdGlvbioqIHwgICAgNi42NCAgICAgfCAgICA2LjYwICAgICB8ICAgIDYuNjUgICAgIHwKfCAgICAgKiooTWluLCBNYXgpKiogICAgIHwgICAoMSwgMjcpICAgfCAgICgxLCAyOCkgICB8ICAgKDEsIDI0KSAgIHwKfCAgICAgICoqKFExLCBRMykqKiAgICAgIHwgICAoMywgMTIpICAgfCAgICgyLCAxMCkgICB8ICAgKDUsIDEyKSAgIHwKCioqKlRhYmxlIDIuMDoqKiBTdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHN0b3JlIGFnZSBmb3IgYWxsIHJlc3RhdXJhbnRzIHBhcnRpY2lwYXRpbmcgaW4gdGhlIG1hcmtldGluZyBjYW1wYWlnbiBzdHVkeS4qCgo8YnIvPgoKYGBge3J9CgojIEFnZSBCb3hwbG90CmRhdGFfMiA9IGRhdGEKZGF0YV8yJFByb21vdGlvbiA9IGFzLmNoYXJhY3RlcihkYXRhXzIkUHJvbW90aW9uKQoKYWdlX3Byb21vX2JveCA9IGdncGxvdChkYXRhXzIsIGFlcyh4PVByb21vdGlvbiwgeT1BZ2VPZlN0b3JlLCBmaWxsPVByb21vdGlvbikpICsgCiAgeWxhYigiQWdlIG9mIFJlc3RhdXJhbnQiKSArCiAgeGxhYigiTWFya2V0aW5nIENhbXBhaWduIikgKwogIGdlb21fYm94cGxvdCgpICsgY29vcmRfZmxpcCgpICsgCiAgZ2VvbV9ib3hwbG90KGNvbG9yPSJibGFjayIpICsgCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSArCiAgZ2VvbV9wb2ludChzaGFwZT0xNiwgcG9zaXRpb249cG9zaXRpb25faml0dGVyKDAuMSksIGNvbG91cj0iYmxhY2siLCBhbHBoYT0uNTApICsKICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyYXk5MCIpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG9yPSJncmF5OTQiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIsIHNpemUgPTAuNSkpICsKICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbD1OQSwgY29sb3VyID0gImdyYXk5MCIsIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gInNvbGlkIikpICsgCiAgdGhlbWUoYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvcj0iZ3JheTkwIiwgc2l6ZT0wLjUpKSArIAogIHRoZW1lKGF4aXMudGlja3MubGVuZ3RoID0gdW5pdCgwLjE4LCAiY20iKSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKYWdlX3Byb21vX2JveApgYGAKCioqKkZpZ3VyZSAzLjA6KiogQm94IHBsb3Qgc2hvd2luZyB0aGUgZGlmZmVyZW5jZSBpbiByZXN0YXVyYW50IGFnZSBkYXRhIGZvciBlYWNoIG9mIHRoZSB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zLiBQcm9tb3Rpb24gMSBpcyBpbiBwdXJwbGUsIFByb21vdGlvbiAyIGlzIGluIGdyZWVuLCBhbmQgUHJvbW90aW9uIDMgaXMgaW4geWVsbG93LioKCjxici8+CgpCb3RoICoqVGFibGUgMi4wKiogYW5kICoqRmlndXJlKiogKiozLjAqKiBzaG93IHRoYXQgdGhlIGFnZSBkaXN0cmlidXRpb25zIGFtb25nIHRoZSB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ24gaXMgdmVyeSBzaW1pbGFyLiBQcm9tb3Rpb24gMSwgMiBhbmQgMyBoYXZlIGEgbWVhbiBhZ2VzIG9mICQ4LjI4JCwgJDcuOTgkLCBhbmQgJDkuMjMkIHJlc3BlY3RpdmVseSBhbmQgYWxsIGhhdmUgc3RhbmRhcmQgZGV2aWF0aW9ucyAkXHNpbSA2LjAkLiBBbGwgaGF2ZSBzb21lIGNsdXN0ZXJpbmcgYXJvdW5kIGFnZSAkMSQsIGFuZCBoYXZlIHNvbWUgb3V0bGllcnMgYWJvdmUgUTMuIEFsbCB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zIGFnZSBkaXN0cmlidXRpb25zIGFyZSBub3QgaWRlbnRpY2FsIGJ1dCB2ZXJ5IHNpbWlsYXIgZm9yIHJlYWwgd29ybGQgZGF0YSBzdGFuZGFyZHMuIFRvIGFuc3dlciBvdXIgZXhwbG9yYXRvcnkgcXVlc3Rpb24sICoqdGhlIGFnZSBvZiByZXN0YXVyYW50IGlzIG5vdCBkaXN0cmlidXRlZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBpbiBlYWNoIG1hcmtldGluZyBjYW1wYWlnbi4qKgoKPGJyLz4KCiMjIyAqKk1hcmtldFNpemUqKgoKTGV0cyBuZXh0IGxvb2sgYXQgdGhlICoqKk1hcmtldFNpemUqKiogdmFyaWFibGUgZm9yIGVhY2ggb2YgdGhlIHRocmVlIG1hcmtldGluZyBjYW1wYWlnbnMuIFRoZSAqKipNYXJrZXRTaXplKioqIHZhcmlhYmxlIGlzIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgdGhhdCBkZXNjcmliZXMgdGhlIG1hcmtldCBzaXplIG9mIGVhY2ggcmVzdGF1cmFudC4gVGhlcmUgYXJlIHRocmVlIG1hcmtldCBzaXplczogc21hbGwsIG1lZGl1bSBhbmQgbGFyZ2UuIFRoZSB0aHJlc2hvbGRzIGFuZCBjcml0ZXJpYSBmb3IgY2F0ZWdvcml6YXRpb24gYXJlIHVua25vd24uCgoqKkV4cGxvcmF0b3J5IFF1ZXN0aW9uOioqIEFyZSBtYXJrZXQgc2l6ZSBwcm9wb3J0aW9ucyBzaW1pbGFyIGluIGVhY2ggbWFya2V0aW5nIGNhbXBhaWduIGdyb3VwPwoKYGBge3IgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQojIFN0YWNrIEJhciBQbG90IChUb3RhbCBTYWxlcykKbWFya2V0X2JhciA9IHBsb3RfbHkoZGF0YSwgeT1+UHJvbW90aW9uLCB4PX5TYWxlc0luVGhvdXNhbmRzLCBjb2xvcj1+TWFya2V0U2l6ZSwgY29sb3JzID0gY29sb3JzXzQsIHR5cGUgPSAiYmFyIikgJT4lCiAgbGF5b3V0KGJhcm1vZGU9InN0YWNrIikgJT4lCiAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZT0iTWFya2V0aW5nIENhbXBhaWduIiwgY2F0ZWdvcnlvcmRlciA9ICJhcnJheSIsIGNhdGVnb3J5YXJyYXkgPSBkYXRhJFByb21vdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICBsaW5lY29sb3IgPSAid2hpdGUiKSkgJT4lCiAgbGF5b3V0KHlheGlzID0gbGlzdChtaW5vciA9IGxpc3Qoc2hvd2dyaWQgPSBGQUxTRSkpKSAlPiUKICBsYXlvdXQoeGF4aXMgPSBsaXN0KHRpdGxlPSJUb3RhbCBTYWxlcyAoaW4gdGhvdXNhbmRzKSIpLCBsZWdlbmQgPSBsaXN0KHRpdGxlPWxpc3QodGV4dD0nTWFya2V0IFNpemUnKSkpCgptYXJrZXRfYmFyCmBgYAoKKioqRmlndXJlIDQuMDoqKiBTdGFja2VkIGJhciBwbG90IHNob3dpbmcgdGhlIGRpZmZlcmVuY2UgaW4gdG90YWwgc2FsZXMgYmV0d2VlbiBtYXJrZXRpbmcgY2FtcGFpZ25zIHN0cmF0aWZpZWQgYnkgbWFya2V0IHNpemUuKgoKPGJyLz4KCkZvciBhbGwgdGhyZWUgY2FtcGFpZ25zIHRoZSBncmVhdGVzdCBwcm9wb3J0aW9uIG9mIHRvdGFsIHNhbGVzIGNhbiBiZSBhdHRyaWJ1dGVkIHRvIG1lZGl1bSBtYXJrZXQgcmVzdGF1cmFudHMsIGxhcmdlIG1hcmtldCByZXN0YXVyYW50cyBhcmUgdGhlIG5leHQgYmlnZ2VzdCBjb250cmlidXRvciB0byB0b3RhbCBzYWxlIG9mIG5ldyBtZW51IGl0ZW1zLCBhbmQgc21hbGwgbWFya2V0IHJlc3RhdXJhbnRzIGNvbnRyaWJ1dGlvbmVkIHRoZSBsZWFzdCBhbW91bnQuIFRoZSBvdmVyYWxsIHRyZW5kIGlzIHNpbWlsYXIgZm9yIGFsbCB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zLgoKYGBge3IgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQojIFN0YWNrIEJhciBQbG90IChDb3VudCkKbWFya2V0X2RhdGEgPSAgZGF0YSAlPiUKZ3JvdXBfYnkoUHJvbW90aW9uLCBNYXJrZXRTaXplKSAlPiUKc3VtbWFyaXplKENvdW50PW4oKSwgc2FsZXNfbWVhbj1tZWFuKFNhbGVzSW5UaG91c2FuZHMpLCBzYWxlc190b3RhbD1zdW0oU2FsZXNJblRob3VzYW5kcykpCgojdmlzdWFsaXppbmcgZGF0YQptYXJrZXRfY291bnRfYmFyID0gcGxvdF9seShtYXJrZXRfZGF0YSwgeT1+UHJvbW90aW9uLCB4PX5Db3VudCwgY29sb3I9fk1hcmtldFNpemUsIGNvbG9ycyA9IGNvbG9yc180LCB0eXBlID0gImJhciIpICU+JQogIGxheW91dChiYXJtb2RlPSJzdGFjayIpICU+JQogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGU9Ik1hcmtldGluZyBDYW1wYWlnbiIsIGNhdGVnb3J5b3JkZXIgPSAiYXJyYXkiLCBjYXRlZ29yeWFycmF5ID0gZGF0YSRQcm9tb3Rpb24sIAogICAgICAgICAgICAgICAgICAgICAgbGluZWNvbG9yID0gIndoaXRlIikpICU+JQogIGxheW91dCh5YXhpcyA9IGxpc3QobWlub3IgPSBsaXN0KHNob3dncmlkID0gRkFMU0UpKSkgJT4lCiAgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZT0iUmVzdGF1cmFudCBDb3VudCIpLCBsZWdlbmQgPSBsaXN0KHRpdGxlPWxpc3QodGV4dD0nTWFya2V0IFNpemUnKSkpCgptYXJrZXRfY291bnRfYmFyCmBgYAoKKioqRmlndXJlIDUuMDoqKiBTdGFja2VkIGJhciBwbG90IHNob3dpbmcgdGhlIGRpZmZlcmVuY2VzIGluIGFtb3VudCBvZiByZXN0YXVyYW50IGluIGVhY2ggb2YgdGhlIHRocmVlIG1hcmtldCBzaXplcyAoc21hbGwsIG1lZGl1bSwgbGFyZ2UpIGZvciBlYWNoIG9mIHRoZSB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zLioKCjxici8+CgpFYWNoIG1hcmtldGluZyBjYW1wYWlnbiBoYXMgdGhlIG1vc3QgYW1vdW50IG9mIG1lZGl1bSBtYXJrZXQgcmVzdGF1cmFudHMgZm9sbG93ZWQgYnkgbGFyZ2UgbWFya2V0IHJlc3RhdXJhbnRzLCBhbmQgdGhlIGxlYXN0IHNtYWxsIG1hcmtldCByZXN0YXVyYW50cy4gUHJvbW90aW9uIDEsIFByb21vdGlvbiAyLCBhbmQgUHJvbW90aW9uIDMgaGFkICQ1NiQsICQ2NCQsIGFuZCAkNDgkIGxhcmdlIG1hcmtldCByZXN0YXVyYW50cyByZXNwZWN0aXZlbHksICQ5NiQsICQxMDgkLCBhbmQgJDExNiQgbWVkaXVtIG1hcmtldCByZXN0YXVyYW50cyByZXNwZWN0aXZlbHksIGFuZCAkMjAkLCAkMTYkLCBhbmQgJDI0JCBzbWFsbCBtYXJrZXQgcmVzdGF1cmFudHMgcmVzcGVjdGl2ZWx5LiBUaGUgb3ZlcmFsbCB0cmVuZCBpcyBzaW1pbGFyIGZvciBhbGwgdGhyZWUgbWFya2V0aW5nIGNhbXBhaWducy4KCkxldHMgY29uc29saWRhdGUgdGhlc2UgdHJlbmRzIGluICoqRmlndXJlIDQuMCoqIGFuZCAqKkZpZ3VyZSA1LjAqKiBpbnRvIG9uZSBzY2F0dGVyIHBsb3QsIHRvIGJlc3QgdmlzdWFsaXplIHRoZSBkaWZmZXJlbnQgYW1vdW50IG9mIHJlc3RhdXJhbnRzIGluIGVhY2ggbWFya2V0IHNpemUgZm9yIGVhY2ggb2YgdGhlIHRocmVlIG1hcmtldGluZyBjYW1wYWlnbnMsIGFuZCBob3cgdGhvc2UgbWFya2V0cyBjb250cmlidXRlZCB0byB0aGUgbWFya2V0aW5nIGdyb3VwcyBzYWxlcy4KCmBgYHtyIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0KbWFya2V0X2NvdW50X3NhbGVzID0gcGxvdF9seShtYXJrZXRfZGF0YSwgeSA9IG1hcmtldF9kYXRhJENvdW50LCB4ID0gbWFya2V0X2RhdGEkc2FsZXNfbWVhbiwgY29sb3IgPSB+UHJvbW90aW9uLCBjb2xvcnMgPSBjb2xvcnNfMywgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdtYXJrZXJzJywgc2l6ZXMgPSBjKDEwLCAxMDApLAogICAgICAgIG1hcmtlciA9IGxpc3Qoc3ltYm9sID0gJ2NpcmNsZScsIHNpemVtb2RlID0gJ2RpYW1ldGVyJywKICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KHdpZHRoID0gMiwgY29sb3IgPSAnYmxhY2snKSksCiAgICAgICAgdGV4dCA9IH5wYXN0ZSgnTWFya2V0aW5nIENhbXBhaWduOicsIFByb21vdGlvbiwgJzxicj5NYXJrZXQ6JywgTWFya2V0U2l6ZSwgJzxicj5SZXN0YXVyYW50IENvdW50OicsIENvdW50LCAnPGJyPlRvdGFsIFNhbGVzOicsIHNhbGVzX3RvdGFsKSkgJT4lCmxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSAnTWVhbiBTYWxlcyAoaW4gdGhvdXNhbmRzKScsCiAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSBjKDAsIDEwMCksCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmV3aWR0aCA9IDIsCiAgICAgICAgICAgICAgICAgICAgdGlja3dpZHRoID0gMS41LAogICAgICAgICAgICAgICAgICAgIHRpY2tsZW4gPSA1LAogICAgICAgICAgICAgICAgICAgIHRpY2twcmVmaXg9IiQiLAogICAgICAgICAgICAgICAgICAgIGdyaWR3aWR0aCA9IDIpLAogICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1Jlc3RhdXJhbnQgQ291bnQnLAogICAgICAgICAgICAgICAgICAgIHJhbmdlID0gYygwLCAxNTApLAogICAgICAgICAgICAgICAgICAgIHplcm9saW5ld2lkdGggPSAyLAogICAgICAgICAgICAgICAgICAgIHRpY2t3aWR0aCA9IDEuNSwKICAgICAgICAgICAgICAgICAgICB0aWNrbGVuID0gNSwKICAgICAgICAgICAgICAgICAgICBncmlkd2l0aCA9IDIpKQoKbWFya2V0X2NvdW50X3NhbGVzCmBgYAoKKioqRmlndXJlIDYuMDoqKiBTY2F0dGVyIHBsb3Qgc2hvd2luZyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTWVhbiBTYWxlcyAoeCkgYW5kIFJlc3RhdXJhbnQgQ291bnQgKHkpIGZvciBhbGwgcmVzdGF1cmFudHMgY29uZHVjdGluZyBtYXJrZXRpbmcgY2FtcGFpZ25zIGZvciBuZXcgbWVudSBpdGVtcy4gQWRkaXRpb25hbGx5LCBpZiB5b3UgaG92ZXIgb3ZlciBlYWNoIHBvaW50IHRoZSBUb3RhbCBTYWxlcyBvZiBlYWNoIHN1YiBncm91cCBpcyBsaXN0ZWQuKgoKPGJyLz4KClRoZSBiaWcgdGFrZSBhd2F5IGZyb20gKipGaWd1cmUgNi4wKiogaXMgdGhhdCAqKlByb21vdGlvbiAyIGhhZCB0aGUgbW9zdCBsYXJnZSBtYXJrZXQgcmVzdGF1cmFudHMsIGJ1dCB0aGUgbG93ZXN0IHRvdGFsIGxhcmdlIG1hcmtldCBzYWxlcyAoKip0aGUgdG90YWwgc2FsZXMgY2FuIGJlIHNlZW4gaWYgeW91IGhvdmVyIG92ZXIgdGhlIGRhdGEgcG9pbnQgaW4gKipGaWd1cmUgNi4wKiopLiBJbiBmYWN0LGFsbCBvZiBQcm9tb3Rpb24gMidzIHJlc3RhdXJhbnRzLCBubyBtYXR0ZXIgdGhlIG1hcmtldCBzaXplLCB1bmRlci1wZXJmb3JtZWQsIGJ1dCBQcm9tb3Rpb24gMidzIGxhcmdlIG1hcmtldCByZXN0YXVyYW50cyB3ZXJlIHRoZSBtb3N0IHNpZ25pZmljYW50IHVuZGVyLXBlcmZvcm1pbmcgbWFya2V0IGZvciB0aGUgUHJvbW90aW9uIDIgY29ob3J0LiAqKkZpZ3VyZSA2LjAqKiBpZGVudGlmaWVzIHRoZSByZWFzb24gUHJvbW90aW9uIDIgaGFzIHRoZSBsb3dlc3QgbWVhbiBzYWxlcywgYnV0IGFsc28gc2hvd3MgdGhhdCBsYXJnZSBtYXJrZXQgcmVzdGF1cmFudHMgdW5kZXItcGVyZm9ybWVkIG1vcmUgdGhhbiBQcm9tb3Rpb24gMidzIHNtYWxsIGFuZCBtZWRpdW0gbWFya2V0IHJlc3RhdXJhbnRzLgoKQW5zd2VyaW5nIG91ciBleHBsb3JhdG9yeSBxdWVzdGlvbiwgdGhlIG1hcmtldCBzaXplIHByb3BvcnRpb25zIHdlcmUgc2ltaWxhciBmb3IgZWFjaCBtYXJrZXRpbmcgY2FtcGFpZ24gZ3JvdXAsIGFuZCBlYWNoIG1hcmtldCBzaXplIGNvbnRyaWJ1dGVkIHByb3BvcnRpb25hbGl0eSBiYXNlZCBvbiB0aGVpciBtYXJrZXQgc2l6ZSB0byB0aGUgdG90YWwgc2FsZXMgb2YgdGhlIG1hcmtldGluZyBjYW1wYWlnbiBncm91cC4gVGhpcyB0cmVuZCBpcyB2aXN1YWxpemVkIGluICoqRmlndXJlIDYuMCoqLCB3aGljaCBzaG93cyB0aHJlZSBjbHVzdGVycy4gYSBzbWFsbCBtYXJrZXQgY2x1c3RlciwgYSBtZWRpdW0gbWFya2V0IGNsdXN0ZXIsIGFuZCBhIGxhcmdlIG1hcmtldCBjbHVzdGVyLiBUaGUgbWVkaXVtIG1hcmtldCBjbHVzdGVyIGhhZCB0aGUgbG93ZXN0IG1lYW4gc2FsZXMsIHdoaWxlIHRoZSBsYXJnZSBtYXJrZXQgaGFkIHRoZSBoaWdoZXN0IG1lYW4gc2FsZXMuCgo8YnIvPgoKIyMjICoqV2VlayoqCgpMYXN0bHksIGxldHMgbG9vayBhdCB0aGUgKioqV2VlayoqKiB2YXJpYWJsZSBmb3IgZWFjaCBvZiB0aGUgdGhyZWUgbWFya2V0aW5nIGNhbXBhaWducy4gVGhlICoqKldlZWsqKiogdmFyaWFibGUgcmFuZ2VzIGZyb20gd2VlayAxIHRocm91Z2ggd2VlazQsIHRpbWUgc3RhbXBpbmcgdGhlIGZvdXIgd2Vla3Mgb2YgbWFya2V0aW5nIGNhbXBhaWduIHN0dWR5LiBTYWxlcyBhbW91bnRzIGZvciBlYWNoIHJlc3RhdXJhbnQgd2VyZSByZWNvcmRlZCBmb3IgZWFjaCBvZiB0aGUgZm91ciB3ZWVrcy4KCioqRXhwbG9yYXRvcnkgUXVlc3Rpb246KiogQXJlIHNvbWUgY2FtcGFpZ25zIHRyZW5kaW5nIGRpZmZlcmVudGx5PyBMb3cgc2FsZXMgaW4gd2VlayAxLCBhbmQgaGlnaGVyIGluIHdlZWsgND8KCmBgYHtyIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTQsIGZpZy5mdWxsd2lkdGg9VFJVRX0KIyBzdGFja2VkIGJhciBwbG90LCBwZXJjZW50CndlZWtfYmFyID0gcGxvdF9seShkYXRhLCB5PX5Qcm9tb3Rpb24sIHg9flNhbGVzSW5UaG91c2FuZHMsIGNvbG9yPX53ZWVrLCBjb2xvcnMgPSBjb2xvcnNfNCwgdHlwZSA9ICJiYXIiKSAlPiUKICBsYXlvdXQoYmFybW9kZT0ic3RhY2siKSAlPiUKICBsYXlvdXQoeWF4aXMgPSBsaXN0KHRpdGxlPSJNYXJrZXRpbmcgQ2FtcGFpZ24iLCBjYXRlZ29yeW9yZGVyID0gImFycmF5IiwgY2F0ZWdvcnlhcnJheSA9IGRhdGEkUHJvbW90aW9uLCAKICAgICAgICAgICAgICAgICAgICAgIGxpbmVjb2xvciA9ICJ3aGl0ZSIpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSBsaXN0KG1pbm9yID0gbGlzdChzaG93Z3JpZCA9IEZBTFNFKSkpICU+JQogIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGU9IlRvdGFsIFNhbGVzIChpbiB0aG91c2FuZHMpIiksIGxlZ2VuZCA9IGxpc3QodGl0bGU9bGlzdCh0ZXh0PSdXZWVrJykpKQoKd2Vla19iYXIKYGBgCgoqKipGaWd1cmUgNy4wOioqIFN0YWNrZWQgYmFyIHBsb3Qgc2hvd2luZyB0aGUgZGlmZmVyZW5jZSBpbiB0b3RhbCBzYWxlcyBiZXR3ZWVuIG1hcmtldGluZyBjYW1wYWlnbnMgYW5kIHRoZSBmb3VyIHdlZWtzIG9mIHRoZSBjYW1wYWlnbi4qCgo8YnIvPgoKVGhlcmUgYXJlIG5vIGNsZWFyIGRpZmZlcmVuY2VzIGluIG1hcmtldGluZyBjYW1wYWlnbiBwZXJmb3JtYW5jZSB3ZWVrIHRvIHdlZWsgZm9yIGFueSBvZiB0aGUgdGhyZWUgcHJvbW90aW9ucy4gVGhlcmUgYXJlIG5vIHZpc2libGUgdHJlbmRzIHRoYXQgc2hvd3MgYW4gaW5jcmVhc2Ugb3IgZGVjcmVhc2UgaW4gbWFya2V0aW5nIGNhbXBhaWduIHBlcmZvcm1hbmNlIHdlZWsgYnkgd2VlayBmb3IgYW55IHByb21vdGlvbi4gRWFjaCBwcm9tb3Rpb25zIHdlZWtseSBwZXJmb3JtYW5jZSBmcm9tIHdlZWsgMSB0aHJvdWdoIHdlZWsgNCBpcyBjb25zaXN0ZW50LCBlYWNoIHdlZWsgYWNjb3VudGluZyBmb3IgYWJvdXQgYSBxdWFydGVyIG9mIHRoZSBtb250aGx5IHNhbGVzLgoKPGJyLz4KCiMgIHsudW5udW1iZXJlZH0KCiMjIyAqKk92ZXJhbGwgQ29uY2x1c2lvbioqCgpUaGUgZGF0YSBmb3IgYWxsIHRocmVlIHVuZGVybHlpbmcgcG9wdWxhdGlvbnMsIFByb21vdGlvbiAxIHJlc3RhdXJhbnRzLCBQcm9tb3Rpb24gMiByZXN0YXVyYW50cywgYW5kIFByb21vdGlvbiAzIHJlc3RhdXJhbnRzLCBpcyBleHRyZW1lbHkgc2ltaWxhciB3aGVuIHdlIGxvb2sgYXQgKioqU2FsZXNJblRob3VzYW5kcyoqKiwgYW5kIGl0cyByZWxhdGlvbiB3aXRoIGFsbCB0aGUgcmVsZXZhbnQgdmFyaWFibGVzOiAqKipBZ2VPZlN0b3JlKioqLCAqKipNYXJrZXRTaXplKioqLCBhbmQgKioqV2VlayoqKi4gU3ltbWV0cnkgaW4gb3VyIGRhdGEgaXMgd2hhdCB3ZXJlIGFyZSBtb3N0IGNvbmNlcm5lZCBhYm91dCB3aGVuIGNvbXBhcmluZyB1bmRlcmx5aW5nIHBvcHVsYXRpb25zLCBhbmQgd2Ugb2JzZXJ2ZWQgbm8gc2lnbmlmaWNhbnQgaXJyZWd1bGFyaXRpZXMuIFdlIGNhbiBjb25maWRlbnRseSBwcm9jZWVkIHRvIGNvbXBhcmluZyB0aGUgKioqU2FsZXNJblRob3VzYW5kcyoqKiBtZWFucyBmb3IgZWFjaCBtYXJrZXRpbmcgY2FtcGFpZ24uCgo8YnIvPiA8YnIvPgoKIyMgMy4gRGVzY3JpYmUgdGhlIHN0YXRpc3RpY2FsIG1ldGhvZHMgeW91IHBsYW4gdG8gdXNlLiB7LnRhYnNldH0KCiMjIyAqKkFuYWx5c2lzIG9mIFZhcmlhbmNlIChBTk9WQSkqKgoKVGhlIGdvYWwgb2YgYSBvbmUtd2F5IGFuYWx5c2lzIG9mIHZhcmlhbmNlIChBTk9WQSkgaXMgdG8gY29tcGFyZSBtZWFucyBhY3Jvc3MgZ3JvdXBzLiBUaGVyZSBhcmUgbWFueSBwcm9jZWR1cmVzIHRvIGNvbXBhcmUgbWVhbnMgYWNyb3NzIHR3byBncm91cHMsIGJ1dCBBTk9WQSBpcyBhIHByb2NlZHVyZSB0aGF0IGV4dGVuZHMgdGhpcyBtZXRob2RvbG9neSB0byBhIHNldHRpbmcgd2hlcmUgdGhlcmUgYXJlIG1vcmUgdGhhbiB0d28gZ3JvdXBzLiBJbiBvdXIgc2NlbmFyaW8sIHdlIGhhdmUgdGhyZWUgZ3JvdXBzLCB0aGUgdGhyZWUgZGlmZmVyZW50IG1hcmtldGluZyBjYW1wYWlnbnMsIGFuZCB3ZSBhcmUgaW50ZXJlc3RpbmcgaW4gY29tcGFyaW5nIG1lYW4gc2FsZXMgb2YgbmV3IG1lbnUgaXRlbXMgYmV0d2VlbiB0aGUgdGhyZWUgY2FtcGFpZ25zLgoKSXQgaXMgaW1wb3J0YW50IHRvIHJlbWVtYmVyIHRoYXQgd2hlbiB3ZSBjb25kdWN0IGFuIEFOT1ZBIHRlc3QsIHdlIGFyZSBjb21wYXJpbmcgYWNyb3NzIHNldmVyYWwgZ3JvdXBzIHdoaWxlIGNvbnNpZGVyaW5nIGFsbCBvZiB0aGUgZGF0YSB0b2dldGhlci4gV2UgaGF2ZSB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zLCBpZiB3ZSBkaWQgbm90IHVzZSBhbiBBTk9WQSB0ZXN0LCB3ZSB3b3VsZCBsaWtlbHkgcmVzb3J0IHRvIHR3by1zYW1wbGUgdC10ZXN0aW5nIGRpZmZlcmVudCBjb21iaW5hdGlvbnMgb2YgdGhlIHRocmVlIG1hcmtldGluZyBjYW1wYWlnbnMuIEhvd2V2ZXIsIGNvbmNsdXNpb25zIGFyZSBvZnRlbiBkaWZmZXJlbnQgd2hlbiBhbGwgbWVhbnMgYXJlIGNvbnNpZGVyZWQgaW5zdGVhZCBvZiBqdXN0IGEgcGFpciBvZiBtZWFucy4gQU5PVkEgYWxsb3dzIHVzIHRvIHRha2UgaW50byBhY2NvdW50IGFsbCB0aHJlZSBtZWFucyBiZWZvcmUgd2UgbWFrZSBhIGNvbmNsdXNpb24uIFRoZSBkaWZmZXJlbmNlIGluIHRoZSB0ZXN0IHN0YXRpc3RpYywgJEYkLCBmcm9tIHRoZSB0ZXN0IHN0YXRpc3RpYyBvZiBhIHR3by1zYW1wbGUgdC10ZXN0IGlzIGZ1bmRhbWVudGFsIHRvIHRoaXMgaWRlYSBvZiB0YWtpbmcgaW50byBhY2NvdW50IG1vcmUgdGhhbiB0d28gbWVhbnMuIFRoZSBlcXVhdGlvbiBmb3IgdGhlIHRlc3Qgc3RhdGlzdGljIGZvciBhbiBBTk9WQSB0ZXN0IGlzIHNob3duIGJlbG93OgoKJCQKRiA9IFxmcmFje1x0ZXh0e0JldHdlZW4gR3JvdXAgVmFyaWFuY2V9fXtcdGV4dHtXaXRoaW4gR3JvdXAgVmFyaWFuY2V9fQokJAoKVGhlIGRldmlhdGlvbiBiZXR3ZWVuIGFuIGluZGl2aWR1YWwgcG9pbnQgYW5kIHRoZSByZXNwZWN0aXZlIGdyb3VwIG1lYW4gaXMgcmVwcmVzZW50YXRpdmUgb2YgdGhlICoqd2l0aGluIGdyb3VwIHZhcmlhbmNlKiouIEluIG91ciBzY2VuYXJpbywgdGhpcyBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBzYWxlcyBvZiBhbiBpbmRpdmlkdWFsIHJlc3RhdXJhbnQgd2hvIGlzIHVzaW5nIFByb21vdGlvbiAxIGFuZCB0aGUgbWVhbiBzYWxlcyBvZiBhbGwgcmVzdGF1cmFudCB3aG8gaXMgdXNpbmcgUHJvbW90aW9uIDEuIFRoZSBkZXZpYXRpb24gYmV0d2VlbiB0aGUgZ3JvdXAgbWVhbiBhbmQgdGhlIG92ZXJhbGwgbWVhbiBpcyByZXByZXNlbnRhdGl2ZSBvZiB0aGUgKipiZXR3ZWVuIGdyb3VwIHZhcmlhbmNlLioqIEluIG91ciBzY2VuYXJpbywgdGhpcyBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBQcm9tb3Rpb24gMSBtZWFuIHNhbGVzIGFuZCB0aGUgbWVhbnMgc2FsZXMgb2YgYWxsIHRocmVlIG1hcmtldGluZyBjYW1wYWlnbnMgKGFuZCB0aGUgc2FtZSBmb3IgdGhlIG90aGVyIHR3byBjYW1wYWlnbnMpLiBUaGVzZSBkZXZpYXRpb25zIGFyZSBzcXVhcmVkIGFuZCB0aGUgc3VtIG92ZXIgYWxsIHBvaW50cyBpcyB0YWtlbiB0byBvYnRhaW4gdGhlIHN1bSBvZiBzcXVhcmVzIHdpdGhpbiBhbmQgdGhlIHN1bSBvZiBzcXVhcmVzIGJldHdlZW4sIHJlc3BlY3RpdmVseS4KClRoYXQgaXMgYSBsb3Qgb2Ygd29yZHMuIFRoZSBpbXBvcnRhbnQgdGFrZSBhd2F5IGZyb20gdGhlIGFib3ZlIGRlc2NyaXB0aW9uIG9mICRGJCBpcyB0aGF0IHRoZSAqKkFOT1ZBIG1ldGhvZG9sb2d5IHRha2VzIGludG8gYWNjb3VudCB0aGUgb3ZlcmFsbCBtZWFuKiogKip3aGVuIGFuYWx5emluZyB2YXJpYW5jZSBvZiBhIGRhdGEgc2V0LioqIEFuZCBiZWNhdXNlIHRoZSBvdmVyYWxsIG1lYW4gaXMgYSBmdW5jdGlvbiBvZiBhbGwgZ3JvdXBzIGluIHRoZSBkYXRhIHNldCwgdGhlIEFOT1ZBIHRlc3QgaXMgZGlmZmVyZW50IHRoYW4gc2ltcGx5IHBlcmZvcm1pbmcgbXVsdGlwbGUgdHdvLXNhbXBsZSB0LXRlc3QsIHdoaWNoIG9ubHkgdXNlcyB0aGUgbWVhbnMgb2YgdHdvIGdyb3Vwcy4KCkEgZ29vZCBydWxlIG9mIHRodW1iIHdoZW4gY29uZHVjdGluZyBBTk9WQSB0ZXN0cyBpcyAqKmlmIHRoZSBiZXR3ZWVuIGdyb3VwIHZhcmlhbmNlIGlzIGxhcmdlIGFuZCB0aGUgd2l0aGluIGdyb3VwIHZhcmlhbmNlIGlzIHNtYWxsLCB0aGVuIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgb2Z0ZW4gcmVqZWN0ZWQqKiBpbiBmYXZvciBvZiB0aGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyB0aGF0IHRoZSB1bmRlcmx5aW5nIG1lYW5zIGFjcm9zcyBncm91cCBhcmUgbm90IGFsbCBlcXVhbC4gSW4gb3VyIHNhbGVzIGRhdGEsIHdlIG9ic2VydmUgdGhlIG9wcG9zaXRlLiBBcyBzZWVuIGluICoqRmlndXJlIDEuMCoqLCB0aGUgYmV0d2VlbiBncm91cCB2YXJpYWJpbGl0eSBpcyBzbWFsbCBhbmQgdGhlIHdpdGhpbiBncm91cCB2YXJpYWJpbGl0eSBpcyBsYXJnZS4gRm9sbG93aW5nIG91ciBydWxlIG9mIHRodW1iIGFib3ZlLCB3ZSBzaG91bGQgZXhwZWN0IHRvIGZhaWwgdG8gcmVqZWN0IG91ciBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgbWVhbiBzYWxlcyBvZiB0aGUgdGhyZWUgbWFya2V0aW5nIGNhbXBhaWducyBhcmUgZXF1YWwuIEFmdGVyIHdlIGNvbmR1Y3Qgb3VyIEFOT1ZBIHRlc3QgYmVsb3csIHdlIHdpbGwgc2VlIGlmIG91ciBoeXBvdGhlc2lzIGlzIGNvcnJlY3QuCgo8YnIvPgoKIyMjICoqVHVrZXkncyBQYWlyd2lzZSBULVRlc3RzKioKClNpbXBseSBwdXQsIHRoZSBwYWlyd2lzZSB0LXRlc3QgZm9yIGFuIEFOT1ZBIHRlc3QgYWxsb3dzIHVzIGRldGVybWluZSBiZXR3ZWVuIHdoaWNoIGdyb3VwcyB0aGUgZGlmZmVyZW5jZXMgKHdlIGRlZW1lZCBzaWduaWZpY2FudCBpbiBvdXIgQU5PVkEgdGVzdCkgbGllLiBUaGUgZXF1YXRpb24gZm9yIHRoZSB0ZXN0IHN0YXRpc3RpYyBmb3IgYSBUdWtleSdzIHBhaXJ3aXNlIHQtdGVzdCBpbiB0aGUgY29udGV4dCBvZiBhbiBBTk9WQSB0ZXN0IGlzIHNob3duIGJlbG93OgoKJCR0ID0gXGZyYWN7XGJhcnt4fV97cHJvbW8tMX0gLSBcYmFye3h9X3twcm9tby0yfX17XHNxcnR7c157Mn1fe3B9KFxmcmFjezF9e25fe3Byb21vLTF9fSArIFxmcmFjezF9e25fe3Byb21vLTJ9fSl9fSQkCgpUaGUga2V5IHRha2UgYXdheSBmcm9tIHRoaXMgZXF1YXRpb24sIGlzIHRoYXQgdGhlICR0JC1zdGF0aXN0aWMgaXMgYSBmdW5jdGlvbiBvZiB0aGUgdmFyaWFuY2UgZnJvbSB0aGUgQU5PVkEsICRzXnsyfV97cH0kLCBhcyBvcHBvc2VkIHRvIHVzaW5nIHRoZSBwb29sZWQgZXN0aW1hdGUgb2YgdGhlIHZhcmlhbmNlIGZyb20gb25seSBncm91cHMgaW52b2x2ZWQgaW4gdGhlIHBhaXJ3aXNlIHQtdGVzdC4gVGhpcyBpcyBhIHdoYXQgZGlmZmVyZW50aWF0ZXMgYSBUdWtleSdzIHBhaXJ3aXNlIHQtdGVzdHMgZm9yIEFOT1ZBIGZyb20gYSByZWd1bGFyIHR3by1zYW1wbGUgdC10ZXN0LiBJZiB3ZSBvbmx5IHVzZWQgdGhlIGRhdGEgZnJvbSBncm91cHMgd2Ugd291bGQgaGF2ZSBlbmRlZCB1cCB3aXRoIGEgc2xpZ2h0bHkgZGlmZmVyZW50IGVzdGltYXRlIG9mIHRoZSB2YXJpYW5jZSwgYW5kIHRodXMgYSBzbGlnaHRseSBkaWZmZXJlbnQgJHQkLXN0YXRpc3RpYy4gQmVjYXVzZSB3ZSAqKmFzc3VtZSB0aGF0IGFsbCBncm91cHMgaGF2ZSB0aGUgc2FtZSB2YXJpYW5jZSB3aGVuIGNvbmR1Y3RpbmcgYW4gQU5PVkEgdGVzdCwqKiB3ZSBkbyBub3Qgd2FudCB0byB1c2UgZGlmZmVyZW50IGVzdGltYXRlcyBvZiB0aGUgdmFyaWFuY2UgaW4gZWFjaCBwYWlyd2lzZSBjb21wYXJpc29uLgoKR2l2ZW4gdGhhdCB0aGUgZXN0aW1hdGUgZnJvbSBBTk9WQSBvZiB0aGUgdmFyaWFiaWxpdHkgaXMgYmFzZWQgb24gbW9yZSBpbmZvcm1hdGlvbiAobW9yZSBvYnNlcnZhdGlvbnMgYXJlIGluY2x1ZGVkKSwgaXQgd2lsbCBiZSBtb3JlIGFjY3VyYXRlIHRoYW4gdGhhdCBvYnRhaW5lZCBmcm9tIHVzaW5nIHRoZSBkYXRhIGZyb20ganVzdCB0d28gb2YgdGhlIGdyb3Vwcy4gT3VyIGVzdGltYXRlIG9mIHZhcmlhYmlsaXR5IGluIGFuIEFOT1ZBIHRlc3QsICRzXnsyfV97cH0kLCBpcyB0aGVyZWZvcmUgY2FsY3VsYXRlZCBmcm9tIGEgbGFyZ2VyIHNhbXBsZSBzaXplIChhbGwgZ3JvdXBzLCBub3QganVzdCB0aGUgZ3JvdXBzIGludm9sdmVkIGluIHRoZSBwYWlyd2lzZSB0LXRlc3QpLiBUaGlzIGVzdGltYXRlIG9mIHZhcmlhYmlsaXR5IGlzIG1vcmUgYWNjdXJhdGUsIGFuZCBpcyBvbmUgb2YgdGhlIHByaW1hcnkgYWR2YW50YWdlcyBvZiBBTk9WQSBwYWlyd2lzZSB0LXRlc3RzLgoKU29tZXRoaW5nIHRvIGtlZXAgaW4gbWluZCB3aGVuIHJ1bm5pbmcgbXVsdGlwbGUgcGFpcndpc2UgdC10ZXN0cyBpcyB0aGF0IHRoZSBtb3JlIHBhaXJ3aXNlIHRlc3RzIHdlIHJ1biB0aGUgbW9yZSBlcnJvcnMgd2UgYXJlIGxpa2VseSB0byBvYnNlcnZlIGR1ZSB0byBjaGFuY2UgYWxvbmUuIFRoZSBtb3JlIHlvdSBkbyBqdXN0IGFib3V0IGFueXRoaW5nIHRoZSBtb3JlIGxpa2VseSB5b3UgYXJlIHRvIG1ha2UgYSBtaXN0YWtlIGJlY2F1c2UgZXZlcnl0aW1lIHlvdSBkbyBzb21ldGhpbmcgeW91IGdpdmUgeW91cnNlbGYgdGhlIG9wcG9ydHVuaXR5IHRvIG1ha2UgYSBtaXN0YWtlLiBJZiB5b3UgZG8gbm90aGluZywgeW91IGNhbid0IG1ha2UgYSBtaXN0YWtlLiBJbiBvdXIgc2NlbmFyaW8sIGFuIGVycm9yIGlzIGEgKipUeXBlIEkgRXJyb3IsIGEgZmFsc2UgcG9zaXRpdmUgY29uY2x1c2lvbioqIChyZWplY3RpbmcgdGhlIG51bGwgaHlwb3RoZXNpcyB3aGVuIGluIHJlYWxpdHkgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyBpbiBmYWN0IHRydWUpLgoKSW4gb3JkZXIgdG8gcmVkdWNlIHRoZSBhbW91bnQgb2YgVHlwZSBJIEVycm9ycyB3ZSBoYXZlIHRvIG1ha2UgaXQgaGFyZGVyIGZvciB1cyB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBkdXJpbmcgb3VyIHBhaXJ3aXNlIHQtdGVzdHMuIE9uZSB3YXkgb2YgZG9pbmcgdGhpcyBpcyB0byBpbmNyZWFzZSBvdXIgY29uZmlkZW5jZSBsZXZlbCAoZGVjcmVhc2luZyAkXGFscGhhJCkuIFRoZXJlZm9yZSwgYXMgd2UgaW5jcmVhc2UgdGhlIG51bWJlciBvZiBwYWlyd2lzZSB0LXRlc3RzIHdlIHJ1biwgd2UgYWxzbyBpbmNyZWFzZSBvdXIgY29uZmlkZW5jZSBsZXZlbCBmb3IgdGhvc2UgcGFpcndpc2UgdC10ZXN0cyBpbiBvcmRlciB0byBiYWxhbmNlIG91dCBvdXIgaW5jcmVhc2luZyBjaGFuY2UgZm9yIGVycm9ycy4gVGhpcyBhbGxvd3MgdXMgdG8gKiptYWludGFpbiBhIHNwZWNpZmllZCBmYW1pbHktd2lzZSBUeXBlIEkgZXJyb3IgcmF0ZSoqLiBGYW1pbHktd2lzZSBUeXBlIEkgZXJyb3IgcmF0ZSBtZWFuaW5nIHRoZSBlcnJvciByYXRlIHdoZW4gbG9va2luZyBhdCBhbGwgcGFpcndpc2UgdC10ZXN0cywgbm90IGp1c3QgdGhlIFR5cGUgSSBlcnJvciByYXRlIG9mIGluZGl2aWR1YWwgcGFpcndpc2UgdC10ZXN0cy4KClByb2NlZHVyZXMgZm9yIGNvbnRyb2xsaW5nIHRoZSBmYW1pbHkgd2lzZSB0eXBlIEkgZXJyb3IgcmF0ZSBhdCBhIHByZS1zcGVjaWZpZWQgbGV2ZWwgYXJlIGNhbGxlZCBtdWx0aXBsZSBjb21wYXJpc29uIHByb2NlZHVyZXMuIEx1Y2tpbHkgZm9yIHVzLCB3ZSBhcmUgb25seSBjb25kdWN0aW5nIHRocmVlIHBhaXJ3aXNlIHRlc3RzLCBidXQgaW4gb3VyIEFOT1ZBIHRlc3Rpbmcgd2Ugd2lsbCBzdGlsbCB1c2UgdGhlICoqVHVrZXkgbXVsdGlwbGUgY29tcGFyaXNvbiBwcm9jZWR1cmUqKiwgYSBjb21wbGV4IHByb2NlZHVyZSB0aGF0IHJlcXVpcmVzIHN0YXRpc3RpY2FsIHNvZnR3YXJlICh3ZSB3aWxsIGJlIHVzaW5nIFIpLiBUaGlzIHdpbGwgcmVkdWNlIG91ciBUeXBlIDEgZXJyb3IgcmF0ZS4KCjxici8+CgojIyMgKipBbmFseXNpcyBvZiBDb3ZhcmlhbmNlIChBTkNPVkEpKioKCkFuYWx5c2lzIG9mIENvdmFyaWFuY2UgKEFOQ09WQSkgaXMgcmVhbGx5IGp1c3QgYSB2YXJpYXRpb24gb2YgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCwgYW5kIGFuIGV4dGVuc2lvbiBvZiB0aGUgQU5PVkEgbWV0aG9kb2xvZ3kuIFdlIGFyZSBzdGlsbCBpbnRlcmVzdGluZyBpbiB0aGUgZGlmZmVyZW50IGdyb3VwIG1lYW5zIGxpa2Ugd2UgYXJlIHdoZW4gZG9pbmcgQU5PVkEsIGJ1dCB3aGVuIGRvaW5nIEFOQ09WQSwgd2UgYXJlIGFkanVzdGluZyB0aG9zZSBncm91cCBtZWFucyBieSBhbm90aGVyIHZhcmlhYmxlLgoKKioqQWdlT2ZTdG9yZSoqKiBpcyB0aGlzIG5ldyB2YXJpYWJsZSB3ZSB3aWxsIGJlIGludHJvZHVjaW5nLCBhbmQgd2Ugd2FudCB0byBjcmVhdGUgYW4gQU5DT1ZBIG1vZGVsIHRvIHNlZSBob3cgdGhlIGFnZSBvZiB0aGUgcmVzdGF1cmFudHMgaW4gYSBjZXJ0YWluIHByb21vdGlvbmFsIGdyb3VwIGltcGFjdHMgc2FsZXMuIFRoZSBxdWVzdGlvbiB3ZSBhcmUgYXNraW5nIHdoZW4gY29uZHVjdGluZyBvdXIgQU5DT1ZBIHRlc3QgaXM6ICoqZG9lcyB0aGUgbWVhbiByZXN0YXVyYW50IHNhbGVzIHN0aWxsIGRpZmZlciBieSBtYXJrZXRpbmcgY2FtcGFpZ24gd2hlbiB0aGUgYWdlIG9mIHJlc3RhdXJhbnRzIGlzIHRha2VuIGludG8gYWNjb3VudD8qKgoKQm90aCBBTkNPVkEgYW5kIEFOT1ZBIHRlc3RpbmcgaW52b2x2ZSBtZWFuIGFuYWx5c2lzOyBob3dldmVyLCB0aGUgbWVhbnMgb2YgdGhlIHVuZGVybHlpbmcgcG9wdWxhdGlvbnMgYXJlIGRpZmZlcmVudC4gV2hlbiB3ZSBjb25kdWN0IGFuIEFOT1ZBIHRlc3Qgd2UgYXJlIGNvbXBhcmluZyBub24tYWRqdXN0ZWQgZ3JvdXAgbWVhbnMsIHdoZXJlIGFzIGluIGFuZCBBTkNPVkEgdGVzdCB3ZSBhcmUgY29tcGFyaW5nIGFkanVzdGVkIGdyb3VwIG1lYW5zLiBXaGVuIHdlIGNvbmR1Y3Qgb3VyIEFOT1ZBIHRlc3Rpbmcgd2Ugd2lsbCBub3QgdGFrZSBpbnRvIGFjY291bnQgKioqQWdlT2ZTdG9yZSoqKiB3aGVuIGFuYWx5emluZyBlYWNoIG1hcmtldGluZyBjYW1wYWlnbnMgbWVhbiBzYWxlcy4gSG93ZXZlciwgd2hlbiB3ZSBjb25kdWN0IG91ciBBTkNPVkEgdGVzdCwgd2UgZG8gdGFrZSBpbnRvIGFjY291bnQgKioqQWdlT2ZTdG9yZSoqKiwgYW5kIGFkanVzdCBvdXIgbWVhbnMgYWNjb3JkaW5nbHkgYmVmb3JlIGFuYWx5emluZyBtYXJrZXRpbmcgY2FtcGFpZ24gbWVhbiBzYWxlcyB2YXJpYW5jZS4gSW4gb3RoZXIgd29yZHMsIHdoZW4gd2UgYXJlIGNvbmR1Y3RpbmcgYW4gQU5DT1ZBIHRlc3QsIHdlIGZvbGxvdyB0aGUgc2FtZSBwcm9jZWR1cmFsIHN0ZXBzIG9mIGFuIEFOT1ZBIHRlc3QganVzdCB3aXRoIGFkanVzdGVkIHVuZGVybHlpbmcgcG9wdWxhdGlvbiBtZWFucy4KCiMgIHsudW5udW1iZXJlZH0KCjxici8+PGJyLz4KCiMjIDQuIFJlcG9ydCB5b3VyIHJlc3VsdHMuIHsudGFic2V0fQoKIyMjICoqQU5PVkEgR2xvYmFsKiogJEYkKiotVGVzdCoqCgoqKlRlc3QgUXVlc3Rpb246KiogRG8gbmV3IG1lbnUgaXRlbSBzYWxlcyBtZWFucyB2YXJ5IGJ5IG1hcmtldGluZyBjYW1wYWlnbj8KClNpbmNlIHdlIGhhdmUgdGhyZWUgZGlmZmVyZW50IHByb21vdGlvbnMsIHdlIHdpbGwgc3RhcnQgd2lsbCBzdGFydCBieSBkb2luZyBhbiBhbmFseXNpcyBvZiB2YXJpYW5jZSAoQU5PVkEpLCBnbG9iYWwgJGYkLXRlc3QuIElmIHRoZXJlIHdlcmUgb25seSB0d28gcHJvbW90aW9uYWwgY2FtcGFpZ25zLCB3ZSBjb3VsZCBzaW1wbHkgZG8gYSBwYWlyd2lzZSAkdCQtdGVzdCB0byBzZWUgaWYgdGhlIHR3byBncm91cHMgZGlmZmVyIGZyb20gZWFjaCBvdGhlci4gUmVhc29ucyBhcmUgZGlzY3Vzc2VkIGFib3ZlLgoKPGJyLz4KCiMjIyMjICoqU1RFUCAxOioqIFNldCB1cCB0aGUgaHlwb3RoZXNlcyBhbmQgc2VsZWN0IHRoZSBhbHBoYSBsZXZlbC4KCiRIX3swfTogXG11X3twcm9tby0xfSA9IFxtdV97cHJvbW8tMn0gPSBcbXVfe3Byb21vLTN9XHRleHR7IChBbGwgcHJvbW90aW9ucyByZXN1bHQgaW4gdGhlIHNhbWUgYW1vdW50IG9mIHNhbGVzKX0kCgokSF97YX06IFxtdV97cHJvbW8tMX0gXG5lIFxtdV97cHJvbW8tMn0gXHRleHR7IG9yIH0gXG11X3twcm9tby0yfSBcbmUgXG11X3twcm9tby0zfSBcdGV4dHsgb3IgfSBcbXVfe3Byb21vLTF9IFxuZSBcbXVfe3Byb21vLTN9XHRleHR7IChOb3QgYWxsIHByb21vdGlvbnMgcmVzdWx0IGluIHRoZSBzYW1lIGFtb3VudCBvZiBzYWxlcyl9JAoKJFxhbHBoYSA9IDAuMDUkCgo8YnIvPgoKIyMjIyMgKipTVEVQIDI6KiogU2VsZWN0IHRoZSBhcHByb3ByaWF0ZSB0ZXN0LXN0YXRpc3RpYywgJGYkLgoKJGYgPSBcZnJhY3tcdGV4dHtNZWFuIFNxdWFyZXMgQmV0d2Vlbn19e1x0ZXh0e01lYW4gU3F1YXJlcyBXaXRoaW59fSQKCjxici8+CgojIyMjIyAqKlNURVAgMzoqKiBTdGF0ZSB0aGUgZGVjaXNpb24gcnVsZS4KClVzZSBSIHRvIGZpbmQgJEZfe2stMSwgbi1rLCBcYWxwaGF9JCBhc3NvY2lhdGVkIHdpdGggYSByaWdodCBoYW5kIHRhaWwgcHJvYmFiaWxpdHkgb2YgJFxhbHBoYSA9IDAuMDUkLgoKYGBge3J9CnFmKDAuOTUsIGRmMT1rLTEsIGRmMj1uLWspCmBgYAoKUmVqZWN0ICRIX3swfTogXG11X3twcm9tby0xfSA9IFxtdV97cHJvbW8tMn0gPSBcbXVfe3Byb21vLTN9JCBpZiBlaXRoZXIgYXJlIFRydWU6CgoxLiAgJGZcZ2UgRl97MiwgNTQ2LCAwLjA1fSA9IDMuMDEkCjIuICAkcCA8IDAuMDUkCgo8YnIvPgoKIyMjIyMgKipTVEVQIDQ6KiogQ29tcHV0ZSB0aGUgdGVzdCBzdGF0aXN0aWMsICRmJCwgYW5kIGFzc29jaWF0ZWQgcC12YWx1ZSwgJHAkIHVzaW5nIGFvdigpLgoKYGBge3J9CiMgT25lLVdheSBBTk9WQQp0ZXN0XzEgPSBhb3YoZm9ybXVsYSA9IFNhbGVzSW5UaG91c2FuZHMgfiBQcm9tb3Rpb24sIGRhdGEgPSBkYXRhKTsgdGVzdF8xCnN1bW1hcnlfdGVzdF8xID0gc3VtbWFyeSh0ZXN0XzEpOyBzdW1tYXJ5X3Rlc3RfMQpgYGAKCiRmID0gMjEuOTUkCgokcCA9IDYuNyoxMF57LTEwfSBcc2ltIDAkCgo8YnIvPgoKIyMjIyMgKipTVEVQIDU6KiogU3RhdGUgeW91ciBjb25jbHVzaW9uLgoKQmVjYXVzZSAkZiA9IDIxLjk1ID4gMy4wMSA9IEZfezIsNTQ2LCAwLjA1fSQsIGFuZCAkcCA9IDYuNyoxMF57LTEwfSA8IDAuMDUgPSBcYWxwaGEkLCB3ZSByZWplY3QgdGhlJEhfezB9OiBcbXVfe3Byb21vLTF9ID0gXG11X3twcm9tby0yfSA9IFxtdV97cHJvbW8tM30kCgpXZSBoYXZlIHN1ZmZpY2llbnQgZXZpZGVuY2UgdGhhdCBhdCB0aGUgJFxhbHBoYSA9IDAuMDUkIGxldmVsIHRoYXQgdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGluIG1lYW4gc2FsZXMgYmV0d2VlbiBtYXJrZXRpbmcgY2FtcGFpZ25zLgoKVG8gYW5zd2VyIG91ciB0ZXN0IHF1ZXN0aW9uLCBzaW5jZSB0aGUgZ2xvYmFsICRmJC10ZXN0IHdhcyBzaWduaWZpY2FudCwgbmV3IG1lbnUgaXRlbXMgc2FsZXMgbWVhbnMgZG8gaW4gZmFjdCB2YXJ5IGJ5IG1hcmtldGluZyBjYW1wYWlnbi4gV2Ugbm93IHdhbnQgdG8gbG9vayBpbnRvIHRoZSBwYWlyd2lzZSBjb21wYXJpc29ucyBvZiB0aGUgc2FsZXMgbWVhbnMgZm9yIGVhY2ggcHJvbW90aW9uLgoKPGJyLz48YnIvPgoKIyMjICoqVHVrZXkncyBQYWlyd2lzZSoqICR0JCoqLVRlc3RzKiogey50YWJzZXR9CgoqKlRlc3QgUXVlc3Rpb246KiogQmV0d2VlbiB3aGljaCBtYXJrZXRpbmcgY2FtcGFpZ25zIGRvZXMgb3VyIGRpZmZlcmVuY2UgbGllPwoKT3VyIGdsb2JhbCBmLXRlc3QgaGFzIGRldGVybWluZWQgdGhhdCB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gbWVhbiBzYWxlcyBiZXR3ZWVuIG1hcmtldGluZyBjYW1wYWlnbnMsIHNvIHdlIHdpbGwgY29uZHVjdCBtdWx0aXBsZSBUdWtleSBQYWlyd2lzZSB0LXRlc3RzIHRvIGRldGVybWluZSB3aGljaCBtYXJrZXRpbmcgY2FtcGFpZ24ncyBtZWFuIHNhbGVzIGRpZmZlci4KClRoZSBzYW1lIFR1a2V5J3MgcGFpcndpc2UgdC10ZXN0aW5nIHByb2NlZHVyZSBzaG93biBmb3IgdGhlIGNvbXBhcmlzb24gb2YgUHJvbW90aW9uIDEgYW5kIFByb21vdGlvbiAyIG1lYW4gc2FsZXMgd2lsbCBiZSB1c2VkIGZvciBjb21wYXJpbmcgUHJvbW90aW9uIDIgYW5kIFByb21vdGlvbiAzIG1lYW4gc2FsZXMsIGFuZCBQcm9tb3Rpb24gMSBhbmQgUHJvbW90aW9uIDMgbWVhbiBzYWxlcy4KCjxici8+CgojIyMjICoqUHJvbW90aW9uIDEgLSBQcm9tb3Rpb24gMioqCgojIyMjIyAqKlNURVAgMToqKiBTZXQgdXAgdGhlIGh5cG90aGVzZXMgYW5kIHNlbGVjdCB0aGUgYWxwaGEgbGV2ZWwuCgokSF97MH06XG11X3twcm9tby0xfSA9IFxtdV97cHJvbW8tMn0kCgokSF97YX06IFxtdV97cHJvbW8tMX0gXG5lIFxtdV97cHJvbW8tMn0kCgokXGFscGhhID0gMC4wNSQKCjxici8+CgojIyMjIyAqKlNURVAgMjoqKiBTZWxlY3QgdGhlIGFwcHJvcHJpYXRlIHRlc3Qtc3RhdGlzdGljLCAkdCQuCgokdCA9IFxmcmFje1xiYXJ7eH1fe3Byb21vLTF9IC0gXGJhcnt4fV97cHJvbW8tMn19e1xzcXJ0e3NeezJ9X3twfShcZnJhY3sxfXtuX3twcm9tby0xfX0gKyBcZnJhY3sxfXtuX3twcm9tby0yfX0pfX0kCgo8YnIvPgoKIyMjIyMgKipTVEVQIDM6KiogU3RhdGUgdGhlIGRlY2lzaW9uIHJ1bGUuCgpgYGB7cn0KcXQoMC45NzUsIGRmID0gbi1rKQpgYGAKClJlamVjdCAkSF97MH06XG11X3twcm9tby0xfSA9IFxtdV97cHJvbW8tMn0kIGlmIGVpdGhlciBhcmUgVHJ1ZToKCjEuICAkdCBcZ2UgVF97bi1rLFxmcmFje1xhbHBoYX17Mn19ID0gMS45Nlx0ZXh0eyAgb3IgIH0gdCBcbGUgLVRfe24tayxcZnJhY3tcYWxwaGF9ezJ9fT0gLTEuOTYkCjIuICAkcCA8IFxmcmFje1xhbHBoYX17Mn0gPSAwLjAyNSBcdGV4dHsgKFJpZ2h0IGhhbmQgdGFpbCBwcm9iYWJpbGl0eSl9JAozLiAgJDAkIGlzIG5vdCB3aXRoaW4gdGhlIGJvdW5kcyBvZiBvdXIgY29uZmlkZW5jZSBpbnRlcnZhbC4KCjxici8+CgojIyMjIyAqKlNURVAgNDoqKiBDb21wdXRlIHRoZSAkdCQtc3RhdGlzdGljLCAkdCQsIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIGFuZCBhc3NvY2lhdGVkIHAtdmFsdWUsICRwJC4KCmBgYHtyfQojIE1hbnVhbCBDYWxjdWxhdGlvbiBvZiB0X3ZhbHVlCnRfdmFsdWUgPSAobWVhbl8xIC0gbWVhbl8yKSAvIHNxcnQoKHN0ZF8xKioyL25fMSArIHN0ZF8yKioyL25fMikpOyB0X3ZhbHVlCiMgV2VsY2ggdC10ZXN0CnQudGVzdChwcm9tb18xJFNhbGVzSW5UaG91c2FuZHMsIHByb21vXzIkU2FsZXNJblRob3VzYW5kcykKCiMgVHVrZXkgQ29tcGFyaXNvbiBvZiBNZWFucwpUdWtleUhTRCh0ZXN0XzEpCiMgTm9uLUFkanVzdGVkIHAtdmFsdWVzICh3aWxsIG5vdCB1c2UganVzdCBmb3IgY2xhcml0eSkKcGFpcndpc2UudC50ZXN0KGRhdGEkU2FsZXNJblRob3VzYW5kcywgZGF0YSRQcm9tb3Rpb24sIHAuYWRqPSJub25lIikKYGBgCgokdCA9IDYuNDMkCgokXHRleHR7Q29uZmlkZW5jZSBJbnRlcnZhbCA9ICg2Ljc3LCAxNC44KX0kCgokcCA9IDQuMjkqMTBeey0xMH0gXHNpbSAwJAoKPGJyLz4KCiMjIyMjICoqU1RFUCA1OioqIFN0YXRlIHlvdXIgY29uY2x1c2lvbi4KCkJlY2F1c2UgJHAgPSA0LjI5KjEwXnstMTB9IDwgMC4wMjUgPSBcZnJhY3tcYWxwaGF9ezJ9JCwgYW5kICR0ID0gNi40MyBcZ2UgMS45NiA9IFRfezU0NSwwLjAyNX0kLCB3ZSByZWplY3QgdGhlICRIX3swfTpcbXVfe3Byb21vLTF9ID0gXG11X3twcm9tby0yfSQKClVzaW5nIHRoZSBUdWtleSBQYWlyd2lzZSBULVRlc3QsIHdlIGhhdmUgc3VmZmljaWVudCBldmlkZW5jZSB0aGF0IGF0IHRoZSAkXGFscGhhID0gMC4wNSQgbGV2ZWwgdGhhdCB0aGUgbWVhbiBzYWxlcyBvZiByZXN0YXVyYW50cyB1c2luZyBQcm9tb3Rpb24gMSwgJFxtdV97cHJvbW8tMX0gPSA1OC4xMCQsIGFuZCByZXN0YXVyYW50cyB1c2luZyBQcm9tb3Rpb24gMiwgJFxtdV97cHJvbW8tMn0gPSA0Ny4zMyQsIGFyZSBkaWZmZXJlbnQgZnJvbSBvbmUgYW5vdGhlci4gVGhlIG9ic2VydmVkIGRpZmZlcmVuY2UgaW4gbWVhbiBzYWxlcyBiZXR3ZWVuIHJlc3RhdXJhbnRzIGNvbmR1Y3RpbmcgUHJvbW90aW9uIDEgYW5kIHJlc3RhdXJhbnRzIGNvbmR1Y3RpbmcgUHJvbW90aW9uIDIgd2FzICQxMC43NyQgdGhvdXNhbmQgZG9sbGFycy4KCldlIGFyZSA5NSUgY29uZmlkZW50IHRoYXQgdGhlIHRydWUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBzYWxlcyBtZWFucyBpcyBiZXR3ZWVuICQ2Ljc3JCBhbmQgJDE0LjgkIHRob3VzYW5kIGRvbGxhcnMuIEFub3RoZXIgaW50ZXJwcmV0YXRpb24gb2Ygb3VyIG51bGwgaHlwb3RoZXNpcyBzdGF0ZXMgdGhhdCAkSF97MH06XG11X3twcm9tby0xfSAtIFxtdV97cHJvbW8tMn0gPSAwJCwgdGVzdGluZyB0byBzZWUgaWYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIG1lYW5zIGlzIHplcm8uIFNpbmNlIGEgZGlmZmVyZW5jZSBvZiAkMCQgaXMgbm90IGluIG91ciBjb25maWRlbmNlIGludGVydmFsLCB3ZSBjYW4gYWdhaW4gcmVqZWN0IHRoZSAkSF97MH06XG11X3twcm9tby0xfSA9IFxtdV97cHJvbW8tMn0kLgoKPGJyLz4KCiMjIyMgKipQcm9tb3Rpb24gMiAtIFByb21vdGlvbiAzKioKCmBgYHtyfQp0X3ZhbHVlID0gKG1lYW5fMiAtIG1lYW5fMykgLyBzcXJ0KChzdGRfMioqMi9uXzIgKyBzdGRfMyoqMi9uXzMpKTsgdF92YWx1ZQp0LnRlc3QocHJvbW9fMyRTYWxlc0luVGhvdXNhbmRzLCBwcm9tb18yJFNhbGVzSW5UaG91c2FuZHMpCmBgYAoKQmVjYXVzZSAkcCA9IDEuNTcqMTBeey02fSA8IDAuMDI1ID0gXGZyYWN7XGFscGhhfXsyfSQsIGFuZCAkdCA9IDQuODggXGdlIDEuOTYgPSBUX3s1NDUsMC4wMjV9JCwgd2UgcmVqZWN0IHRoZSAkSF97MH06XG11X3twcm9tby0yfSA9IFxtdV97cHJvbW8tM30kCgpVc2luZyB0aGUgVHVrZXkgUGFpcndpc2UgVC1UZXN0LCB3ZSBoYXZlIHN1ZmZpY2llbnQgZXZpZGVuY2UgdGhhdCBhdCB0aGUgJFxhbHBoYSA9IDAuMDUkIGxldmVsIHRoYXQgdGhlIG1lYW4gc2FsZXMgb2YgcmVzdGF1cmFudHMgdXNpbmcgUHJvbW90aW9uIDIsICRcbXVfe3Byb21vLTJ9ID0gNDcuMzMkLCBhbmQgcmVzdGF1cmFudHMgdXNpbmcgUHJvbW90aW9uIDMsICRcbXVfe3Byb21vLTN9ID0gNTUuMzYkLCBhcmUgZGlmZmVyZW50IGZyb20gb25lIGFub3RoZXIuIFRoZSBvYnNlcnZlZCBkaWZmZXJlbmNlIGluIG1lYW4gc2FsZXMgYmV0d2VlbiByZXN0YXVyYW50cyBjb25kdWN0aW5nIFByb21vdGlvbiAyIGFuZCByZXN0YXVyYW50cyBjb25kdWN0aW5nIFByb21vdGlvbiAzIHdhcyAkLTguMDMkIHRob3VzYW5kIGRvbGxhcnMuCgpXZSBhcmUgOTUlIGNvbmZpZGVudCB0aGF0IHRoZSB0cnVlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgc2FsZXMgbWVhbnMgaXMgYmV0d2VlbiAkLTQuMTIkIGFuZCAkLTExLjk1JCB0aG91c2FuZCBkb2xsYXJzLiBBbm90aGVyIGludGVycHJldGF0aW9uIG9mIG91ciBudWxsIGh5cG90aGVzaXMgc3RhdGVzIHRoYXQgJEhfezB9OlxtdV97cHJvbW8tMn0gLSBcbXVfe3Byb21vLTN9ID0gMCQsIHRlc3RpbmcgdG8gc2VlIGlmIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBtZWFucyBpcyB6ZXJvLiBTaW5jZSBhIGRpZmZlcmVuY2Ugb2YgXCQwXCQgaXMgbm90IGluIG91ciBjb25maWRlbmNlIGludGVydmFsLCB3ZSBjYW4gYWdhaW4gcmVqZWN0IHRoZSAkSF97MH06XG11X3twcm9tby0yfSA9IFxtdV97cHJvbW8tM30kLgoKPGJyLz4KCiMjIyMgKipQcm9tb3Rpb24gMSAtIFByb21vdGlvbiAzKioKCmBgYHtyfQp0X3ZhbHVlID0gKG1lYW5fMSAtIG1lYW5fMykgLyBzcXJ0KChzdGRfMSoqMi9uXzEgKyBzdGRfMyoqMi9uXzMpKTsgdF92YWx1ZQp0LnRlc3QocHJvbW9fMSRTYWxlc0luVGhvdXNhbmRzLCBwcm9tb18zJFNhbGVzSW5UaG91c2FuZHMpCmBgYAoKQmVjYXVzZSAkcCA9IDAuMjQgPiAwLjAyNSA9IFxmcmFje1xhbHBoYX17Mn0kLCBhbmQgJHQgPSAxLjU1IDwgMS45NiA9IFRfezU0NSwwLjAyNX0kLCB3ZSBmYWlsIHRvIHJlamVjdCB0aGUgJEhfezB9OlxtdV97cHJvbW8tMX0gPSBcbXVfe3Byb21vLTN9JAoKVXNpbmcgdGhlIFR1a2V5IFBhaXJ3aXNlIFQtVGVzdCwgd2UgaGF2ZSBzdWZmaWNpZW50IGV2aWRlbmNlIHRoYXQgYXQgdGhlICRcYWxwaGEgPSAwLjA1JCBsZXZlbCB0aGF0IHRoZSBtZWFuIHNhbGVzIG9mIHJlc3RhdXJhbnRzIHVzaW5nIFByb21vdGlvbiAxLCAkXG11X3twcm9tby0xfSA9IDU4LjEwJCwgYW5kIHJlc3RhdXJhbnRzIHVzaW5nIFByb21vdGlvbiAzLCAkXG11X3twcm9tby0zfSA9IDU1LjM2JCwgYXJlIGRpZmZlcmVudCBmcm9tIG9uZSBhbm90aGVyLiBUaGUgb2JzZXJ2ZWQgZGlmZmVyZW5jZSBpbiBtZWFuIHNhbGVzIGJldHdlZW4gcmVzdGF1cmFudHMgY29uZHVjdGluZyBQcm9tb3Rpb24gMSBhbmQgcmVzdGF1cmFudHMgY29uZHVjdGluZyBQcm9tb3Rpb24gMyB3YXMgJC0yLjczJCB0aG91c2FuZCBkb2xsYXJzLgoKV2UgYXJlIDk1JSBjb25maWRlbnQgdGhhdCB0aGUgdHJ1ZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHNhbGVzIG1lYW5zIGlzIGJldHdlZW4gJC0xLjI2JCBhbmQgJDYuNzQkIHRob3VzYW5kIGRvbGxhcnMuIEFub3RoZXIgaW50ZXJwcmV0YXRpb24gb2Ygb3VyIG51bGwgaHlwb3RoZXNpcyBzdGF0ZXMgdGhhdCAkSF97MH06XG11X3twcm9tby0xfSAtIFxtdV97cHJvbW8tM30gPSAwJCwgdGVzdGluZyB0byBzZWUgaWYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIG1lYW5zIGlzIHplcm8uIFNpbmNlIGEgZGlmZmVyZW5jZSBvZiAkMCQgaXMgaW4gb3VyIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIHdlIGFsc28gZmFpbCB0byByZWplY3QgdGhlICRIX3swfTpcbXVfe3Byb21vLTF9ID0gXG11X3twcm9tby0zfSQuCgo8YnIvPgoKIyMjICoqQU5DT1ZBKioKCioqVGVzdCBRdWVzdGlvbjoqKiBEb2VzIHRoZSBtZWFuIHJlc3RhdXJhbnQgc2FsZXMgc3RpbGwgZGlmZmVyIGJ5IG1hcmtldGluZyBjYW1wYWlnbiB3aGVuIHRoZSBhZ2Ugb2YgcmVzdGF1cmFudHMgaXMgdGFrZW4gaW50byBhY2NvdW50PwoKVGhyb3VnaCBvdXIgaW52ZXN0aWdhdGlvbiBvZiBvdXIgZGF0YSBpbiBQYXJ0IDEsIHdlIGhhdmUgbm8gcmVhc29uIHRvIHN1c3BlY3QgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuICoqKlNhbGVzSW5UaG91c2FuZHMqKiosIGFuZCAqKipBZ2VPZlN0b3JlKioqLCAqKipNYXJrZXRTaXplKioqLCBvciAqKipXZWVrKioqLiBIb3dldmVyLCBmb3IgY29tcGxldGVuZXNzLCBsZXRzIGxvb2sgYXQgdGhlICoqKkFnZU9mU3RvcmUqKiogdmFyaWFibGUsIGFuZCBjb25kdWN0IGEgcXVpY2sgQU5PVkEgdGVzdCB1c2luZyBSIHRvIGNvbmZpcm0gdGhhdCBpdCBoYXMgbm8gZWZmZWN0IG9uIHRoZSB2YXJpYW5jZSBpbiBtZWFuIHNhbGVzIGJldHdlZW4gbWFya2V0aW5nIGNhbXBhaWducy4KCmBgYHtyfQojIEludGVyZXN0ZWQgaW4gbWVhbiBzYWxlcywgQWRqdXN0aW5nIGZvciBBZ2UKIyBPUkRFUiBNQVRURVJTIHdoZW4geW91IHVzZSBhb3YoKQphbmNvdmFfbW9kZWwgPSBhb3YoU2FsZXNJblRob3VzYW5kcyB+IFByb21vdGlvbiArIEFnZU9mU3RvcmUsIGRhdGEgPSBkYXRhKQpgYGAKCmBgYHtyfQpBbm92YShhbmNvdmFfbW9kZWwsIHR5cGU9IklJSSIpCmBgYAoKKioqVGFibGUgNS4wOioqIEFOT1ZBIFRhYmxlIGZvciBvdXIgQU5DT1ZBIE1vZGVsIHRoYXQgdGFrZXMgaW50byBhY2NvdW50IGJvdGggbWFya2V0aW5nIGNhbXBhaWduICgqKlByb21vdGlvbioqKSBhbmQgKipBZ2VPZlN0b3JlKiouKgoKPGJyLz4KCldlIHNlZSBpbiAqKlRhYmxlIDUuMCoqIHRoYXQgKioqQWdlT2ZTdG9yZSoqKiBpcyBub3Qgc2lnbmlmaWNhbnRseSBhc3NvY2lhdGVkIHdpdGggdGhlIG1lYW4gc2FsZXMgb2YgYSByZXN0YXVyYW50IHdpdGggYSBsYXJnZSAkcCA9IDAuMzMyNiQsIHdoaWxlIHRoZSBtYXJrZXRpbmcgY2FtcGFpZ24gcmVtYWlucyB0byBiZSBzaWduaWZpY2FudGx5IGFzc29jaWF0ZWQgd2l0aCB0aGUgbWVhbiBzYWxlcyB3aXRoIGEgc21hbGwgJHAgPSA1LjQ5KjEwXnstMTB9JC4gQWRkaXRpb25hbGx5LCB0aGUgJGYkLXN0YXRpc3RpYyBmb3IgdGhlIG1hcmtldGluZyBjYW1wYWlnbiB2YXJpYWJsZSBoYXMgbm90IGNoYW5nZWQsIHJlbWFpbmluZyBoaWdoIGF0IGFyb3VuZCAkMjIkLgoKVGhlcmVmb3JlLCB3ZSBkbyBub3QgaGF2ZSBzdWZmaWNpZW50IGV2aWRlbmNlIGF0IHRoZSAkXGFscGhhID0gMC4wNSQgbGV2ZWwgdGhhdCB0aGUgZGlmZmVyZW5jZSBpbiBhbW91bnQgb2Ygc2FsZXMgYmV0d2VlbiBtYXJrZXRpbmcgY2FtcGFpZ25zIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgKioqQWdlT2ZTdG9yZSoqKi4gVGhpcyBtZWFucyB0aGF0IHRoZSBtZWFuIHNhbGVzIG9mIGVhY2ggbWFya2V0aW5nIGNhbXBhaWduIHdpbGwgbm90IGNoYW5nZSBzaWduaWZpY2FudGx5IHdoZW4gd2UgdGFrZSBpbnRvIGFjY291bnQgKioqQWdlT2ZTdG9yZSoqKi4gVGhlcmVmb3JlLCB0aGVyZSBpcyBubyBuZWVkIHRvIGxvb2sgYXQgdGhlIHBhaXJ3aXNlIGNvbXBhcmlzb25zIG9mIHRoZSBzYWxlcyBudW1iZXJzIGZvciBlYWNoIHByb21vdGlvbiBhZnRlciBhZGp1c3RpbmcgZm9yICoqKkFnZU9mU3RvcmUqKiouCgojIyAgey51bm51bWJlcmVkfQoKPGJyLz4KCiMjIDUuIFN0YXRlIHlvdXIgY29uY2x1c2lvbnMgYW5kIGRpc2N1c3MgYW55IGxpbWl0YXRpb25zLiB7LnRhYnNldH0KCiMjIyAqKkNvbmNsdXNpb25zKioKCldlIGNvbmNsdWRlZCB0aGF0ICoqZ2xvYmFsbHkgdGhhdCB0aGVpciB3YXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbnQgYmV0d2VlbiBtYXJrZXRpbmcgY2FtcGFpZ25zIG1lYW4gc2FsZXMqKi4gSW4gdGhlIGNvbnRleHQgb2Ygb3VyIHF1ZXN0aW9uLCB0aGlzIGluZGljYXRlcyB0aGF0IHdlIG5lZWQgdG8gZmlndXJlIG91dCBiZXR3ZWVuIHdoaWNoIG1hcmtldGluZyBjYW1wYWlnbnMgdGhlIGRpZmZlcmVuY2UgbGllcywgc28gd2UgY2FuIGlkZW50aWZ5IHRoZSBzcGVjaWZpYyBtYXJrZXRpbmcgY2FtcGFpZ24gdGhhdCBpcyBnZW5lcmF0aW5nIHRoZSBtb3N0IHNhbGVzLgoKfCBDb21wYXJpc29uICAgICAgICB8ICR0JC1zdGF0aXN0aWMgfCAkcF97dHVrZXl9JCB2YWx1ZSB8IENvbmNsdXNpb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwtLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8IFByb21vIDEgLSBQcm9tbyAyIHwgNi40MyAgICAgICAgICB8IDAgICAgICAgICAgICAgICAgIHwgU2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIG1lYW5zLiAgIHwKfCBQcm9tbyAyIC0gUHJvbW8gMyB8IDQuODggICAgICAgICAgfCAwLjAwMDAwNTUgICAgICAgICB8IFNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBtZWFucy4gICB8CnwgUHJvbW8gMSAtIFByb21vIDMgfCAxLjU1ICAgICAgICAgIHwgMC4yNCAgICAgICAgICAgICAgfCBJbnNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBtZWFucy4gfAoKKioqVGFibGUgNi4wOioqIFN1bW1hcnkgb2YgVHVrZXkncyBQYWlyd2lzZSBULVRlc3QgcmVzdWx0cy4qIDxici8+CgpXaGVuIGxvb2tpbmcgYXQgdGhlIGRpZmZlcmVuY2VzIGluIG1lYW4gc2FsZXMgYmV0d2VlbiBtYXJrZXRpbmcgY2FtcGFpZ25zLCBib3RoICoqUHJvbW90aW9uIDEgYW5kIFByb21vdGlvbiAzIHdlcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgdGhhdCBQcm9tb3Rpb24gMiwgYnV0IG5vdCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIG9uZSBhbm90aGVyLioqIEJvdGggUHJvbW90aW9uIDEgYW5kIFByb21vdGlvbiAzIGhhdmUgaGlnaGVyIG1lYW5zIHRoYW4gUHJvbW90aW9uIDIsIG1lYW5pbmcgdGhlc2UgYXJlIHRoZSB0d28gY2FtcGFpZ25zIHRoYXQgcmVzdWx0ZWQgaW4gbW9yZSBuZXcgbWVudSBpdGVtcyBzYWxlcyB0aGFuIHRoYW4gdGhlIFByb21vdGlvbiAyIG1hcmtldGluZyBjYW1wYWlnbi4gQm90aCBQcm9tb3Rpb24gMSBhbmQgUHJvbW90aW9uIDMgbWVhbiBzYWxlcyBmaWd1cmVzIHdlcmUgZGlmZmVyZW50IGZyb20gb25lIGFub3RoZXIsIGJ1dCBub3Qgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYXQgdGhlICRcYWxwaGEgPSAwLjA1JCBsZXZlbC4gVGhlcmVmb3JlLCBlaXRoZXIgdGhlIFByb21vdGlvbiAxIG9yIFByb21vdGlvbiAzIG1hcmtldGluZyBjYW1wYWlnbiBzaG91bGQgYmUgcHJlZmVycmVkIG92ZXIgdGhlIFByb21vdGlvbiAyIG1hcmtldGluZyBjYW1wYWlnbiBpbiBvcmRlciB0byBpbmNyZWFzZXMgdGhlIHRvdGFsIHNhbGVzIG9mIG5ldyBtZW51IGl0ZW1zLiBUbyBhbnN3ZXIgb3VyIHJlc2VhcmNoIHF1ZXN0aW9uLCAqKlByb21vdGlvbiAxIGFuZCBQcm9tb3Rpb24gMyBtYXJrZXRpbmcgY2FtcGFpZ25zIGFyZSBtb3N0IGxpa2VseSB0byByZXN1bHQgaW4gdGhlIGdyZWF0ZXN0IGluY3JlYXNlIGluIHNhbGVzIG9mIG5ldyBtZW51IGl0ZW1zIGZvciB0aGUgcmVzdGF1cmFudCBjaGFpbi4qKgoKYGBge3J9ClR1a2V5SFNEKHRlc3RfMSwgY29uZi5sZXZlbCA9IDAuOTkpCmBgYAoKRXZlbiBpZiB3ZSBjb25kdWN0IGEgVHVrZXkgUGFpcndpc2UgVC1UZXN0IGF0IHRoZSAkXGFscGhhID0gMC4wMSQgbGV2ZWwsIHRoZSByZXN1bHRzIGFyZSB0aGUgc2FtZSwgc28gdGhlIHJlc3RhdXJhbnQgc2hvdWxkIGZlZWwgY29uZmlkZW50IG1vdmluZyBmb3J3YXJkcyB3aXRoIGVpdGhlciBQcm9tb3Rpb24gMSBvciBQcm9tb3Rpb24gMyBtYXJrZXRpbmcgY2FtcGFpZ25zLCBhbmQgc2hvdWxkIGNvbnNpZGVyIGxvb2tpbmcgaW50byBvdGhlciBtYXJrZXRpbmcgY2FtcGFpZ24gZmFjdG9ycywgY29zdHMgb2YgdGhlIGNhbXBhaWducywgZWFzZSBvZiBpbXBsZW1lbnRhdGlvbiwgc3RheWluZyBwb3dlciwgZXRjLiB0byBkZXRlcm1pbmUgd2hpY2ggb2YgdGhlIHR3byBjYW1wYWlnbnMgdG8gaW1wbGVtZW50IGFjcm9zcyBhbGwgcmVzdGF1cmFudHMuCgpPdXIgKipBTkNPVkEgdGVzdGluZyoqIGFkanVzdGluZyBmb3IgKioqQWdlT2ZTdG9yZSoqKiBzaG93ZWQgbm8gY29ycmVsYXRpb24gYmV0d2VlbiAqKipBZ2VPZlN0b3JlKioqIGFuZCAqKipTYWxlc0luVGhvdXNhbmRzKioqIG1lYW5zIGZvciBlYWNoIG1hcmtldGluZyBjYW1wYWlnbi4gTWVhbmluZywgZXZlbiB3aGVuICoqKkFnZU9mU3RvcmUqKiogd2FzIHRha2VuIGludG8gYWNjb3VudCwgd2UgZGlkIG5vdCBjaGFuZ2Ugb3VyIGNvbmNsdXNpb24gZnJvbSBvdXIgb3JpZ2luYWwgQU5PVkEgdGVzdCwgYW5kIG1haW50YWluIHRoYXQgYXQgdGhlICRcYWxwaGEgPSAwLjA1JCBsZXZlbCwgbWVhbiBzYWxlcyBkaWZmZXJlbmNlIGJldHdlZW4gZm9yIFByb21vdGlvbiAxLCBQcm9tb3Rpb24gMiwgYW5kIFByb21vdGlvbiAzIGFyZSBhc3NvY2lhdGVkIHdpdGggbWFya2V0aW5nIGNhbXBhaWduLgoKTGFzdGx5LCB3ZSBoYXZlIGEgdGhyZWUgdG9waWNzIHdlIHdhbnRlZCB0byBjaXJjbGUgYmFjayB1cG9uIGFmdGVyIHdlIHRlc3RlZCBvdXIgZGF0YS4gSW4gcmVnYXJkcyB0byB0aGUgMzAgc2FsZXMgb3V0bGllcnMgZm91bmQgaW4gdGhlIFByb21vdGlvbiAyIHN1YnNldCBkaXNjdXNzZWQgaW4gb3VyIGV4cGxvcmF0aW9uIG9mIHRoZSBkYXRhLCB0aGVzZSB3aWxsIGhhdmUgbm8gaW1wYWN0IG9uIG91ciBmaW5hbCBjb25jbHVzaW9ucy4gVGhlc2Ugb3V0bGllcnMgYWxsIGZhbGwgYWJvdmUgdGhlIG1lYW4sIGFuZCB0aGVyZWZvcmUgZHJhZyB0aGUgbWVhbiB1cCwgZ2l2aW5nIFByb21vdGlvbiAyIGFuIGFydGlmaWNpYWxseSBsYXJnZSBtZWFuLiBJZiB0aGVzZSBvdXRsaWVycyB3ZXJlIHJlbW92ZWQsIGFsb25nIHdpdGggdGhlIG91dGxpZXJzIGZvciB0aGUgb3RoZXIgbWFya2V0aW5nIGNhbXBhaWducywgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBQcm9tb3Rpb24gMiBzYWxlcyBtZWFuIGFuZCB0aGUgc2FsZXMgbWVhbnMgb2YgUHJvbW90aW9uIDEgYW5kIFByb21vdGlvbiAzIHdvdWxkIGJlIGV2ZW4gbW9yZSBzaWduaWZpY2FudC4gVGhlcmVmb3JlLCB3ZSBjYW4gZGlzcmVnYXJkIHRoZSBlZmZlY3Qgb2YgdGhlc2Ugb3V0bGllcnMgd2hlbiBtYWtpbmcgb3VyIGNvbmNsdXNpb24uCgpBZnRlciBjb25jbHVkaW5nIG1lYW4gc2FsZXMgZm9yIFByb21vdGlvbiAyIHRvIGJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gUHJvbW90aW9uIDIgYW5kIDMsIHdlIHNob3VsZCBnaXZlIG1vcmUgY3JlZGVuY2UgdG8gb3VyIGRpc2N1c3Npb24gcmVnYXJkaW5nICoqRmlndXJlIDYuMCoqLiBBbmQgSSB3b3VsZCByZWNvbW1lbmQgdGhhdCB0aGUgcmVzdGF1cmFudCBjaGFpbiBpbnZlc3RpZ2F0ZSBQcm9tb3Rpb24gMidzIGxhcmdlIG1hcmtldCByZXN0YXVyYW50cyB0byB1bmRlcnN0YW5kIHdoeSB0aGV5IG1heSBoYXZlIHVuZGVyLXBlcmZvcm1lZC4gVGhpcyBtYXkgZ2l2ZSBjbGFyaXR5IHRvIHNvbWUgb2YgdGhlIGNhdXNlcyBvZiB0aGUgYXNzb2NpYXRpb24gd2UgZm91bmQgYmV0d2VlbiBtYXJrZXRpbmcgY2FtcGFpZ24gYW5kIG1lYW4gc2FsZXMuCgpGaW5hbGx5LCBvdXIgZGF0YSBkaWQgbm90IGZvbGxvdyB0aGUgQU5PVkEgcnVsZSBvZiB0aHVtYiB0aGF0ICoqaWYgdGhlIGJldHdlZW4gZ3JvdXAgdmFyaWFuY2UgaXMgc21hbGwgYW5kIHRoZSB3aXRoaW4gZ3JvdXAgdmFyaWFuY2UgaXMgbGFyZ2UgdGhlbiBpdCBpcyBsaWtlbHkgdGhhdCB0aGUgdW5kZXJseWluZyBtZWFucyBhcmUgYWxsIGVxdWFsLioqIERlc3BpdGUgdGhpcywgd2UgZGlkIGZpbmQgdGhlIHVuZGVybHlpbmcgbWVhbnMgd2VyZSBub3QgYWxsIGVxdWFsLCBhbmQgdGhlcmUgd2FzIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB1bmRlcmx5aW5nIHBvcHVsYXRpb24gbWVhbnMuIFRoaXMgc2hvd3MgdGhlIGltcG9ydGFudCBvZiB0ZXN0aW5nLCBkb2luZyB0aGUgYWN0dWFsIG1hdGggKHRoYW5rIHlvdSBSKSwgZXZlbiB3aGVuIHRoZSBkYXRhIGlzIHZpc3VhbGx5IGNvbW11bmljYXRpbmcgYSBzZWVtaW5nbHkgY2xlYXIgY29uY2x1c2lvbi4KCjxici8+CgojIyMgKipBc3N1bXB0aW9ucyoqCgpJbiBvcmRlciB0byBtYWtlIGluZmVyZW5jZXMgdXNpbmcgQU5PVkEgbWV0aG9kb2xvZ3ksIHdlIGhhdmUgdG8gbWFrZSBzdXJlIHRocmVlIGNvbmRpdGlvbnMgYXJlIG1ldDoKCjEuICAqKkluZGVwZW5kZW50LCByYW5kb20gc2FtcGxlcyBmcm9tIGVhY2ggZ3JvdXAgaW4gdGhlIHBvcHVsYXRpb24uKioKCk91ciBkYXRhIHNvdXJjZSBzdGF0ZWQgdGhhdCBlYWNoIHJlc3RhdXJhbnQgaW4gdGhlIG1hcmtldGluZyBzdHVkeSB3YXMgY2hvc2VuIGF0IHJhbmRvbSBmcm9tIGFsbCBvZiB0aGUgY29tcGFuaWVzIHJlc3RhdXJhbnRzLiBGdXJ0aGVybW9yZSwgdGhlIG1hcmtldGluZyBjYW1wYWlnbiBhc3NpZ25lZCB0byBlYWNoIHJlc3RhdXJhbnQgd2FzIGFsc28gY2hvc2VuIGF0IHJhbmRvbS4gRWFjaCByZXN0YXVyYW50IHdhcyBvbmx5IHRlc3RlZCBvbmNlLCBmb3Igb25lIG1hcmtldGluZyBjYW1wYWlnbiBvdmVyIG9uZSBtb250aC4gQXNzdW1wdGlvbiAxIGlzIHRoZXJlZm9yZSBtZXQuCgoyLiAgKipPdXRjb21lIG9mIGludGVyZXN0IGluIGdyb3VwL3BvcHVsYXRpb24gaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgd2l0aCB1bmtub3duIG1lYW4qKgozLiAgKipPdXRjb21lIG9mIGludGVyZXN0IGluIGVhY2ggZ3JvdXAvcG9wdWxhdGlvbiBoYXMgYSBzaW1pbGFyIHVua25vd24gc3RhbmRhcmQgZGV2aWF0aW9uKioKCkxldHMgZ3JhcGhzIHNvbWUgaGlzdG9ncmFtcyBvZiBvdXIgb3V0Y29tZSBvZiBpbnRlcmVzdCwgKioqU2FsZXNJblRob3VzYW5kcywqKiogZm9yIGVhY2ggZ3JvdXAsICoqKlByb21vdGlvbioqKiwgaW4gb3JkZXIgdG8gY2hlY2sgZm9yIG5vcm1hbGl0eSBhbmQgdmFyaWFuY2Ugc2ltaWxhcml0eS4KCmBgYHtyfQojIERpc3RyaWJ1dGlvbnMKIyMgUHJvbW90aW9uIDEgKENvZGUgZm9yIFByb21vdGlvbiAyIGFuZCAzIGFyZSBpZGVudGljYWwsIGJ1dCBoaWRkZW4pCmJyZWFrcyA9IHNlcShmcm9tID0gMjAsIHRvID0gMTAwLCBieT0yKQoKcHJvbW9fMV9oaXN0ID0gZ2dwbG90KHByb21vXzEsIGFlcyh4PVNhbGVzSW5UaG91c2FuZHMpKSArIAogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBicmVha3MgPSBicmVha3MsIGNvbG9yPSdncmF5ODAnLCBmaWxsPSJncmF5ODAiKSArIAogIGdndGl0bGUoJ1Byb21vdGlvbiAxIFNhbGVzIERlbnNpdHkgSGlzdHJvZ3JhbScpICsKICB4bGFiKCJTYWxlcyAoaW4gdGhvdXNhbmRzKSIpICsKICB5bGFiKCJEZW5zaXR5IikgKyAKICBnZW9tX2RlbnNpdHkoY29sb3IgPSAiYmxhY2siLCBmaWxsPWNvbG9yc180WzFdLCAgYWxwaGE9MC41KSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4ocHJvbW9fMSRTYWxlc0luVGhvdXNhbmRzKSwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSdkYXJrYmx1ZScsIHNpemUgPSAwLjgpICsKICBhbm5vdGF0ZSgidGV4dCIsY29sb3I9J2RhcmtibHVlJywgc2l6ZSA9IDMsIHg9bWVhbihwcm9tb18xJFNhbGVzSW5UaG91c2FuZHMpKzEuMjUsIHk9MC4wMDc1LCAKICAgICAgICAgIGxhYmVsPSBwYXN0ZSgiTWVhbiBTYWxlcyA9Iiwgcm91bmQobWVhbihwcm9tb18xJFNhbGVzSW5UaG91c2FuZHMpLCAyKSksIGFuZ2xlPTkwKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvcj0iZ3JheTkwIiksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyYXk5NCIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiwgc2l6ZSA9MC41KSkgKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsPU5BLCBjb2xvdXIgPSAiZ3JheTkwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAic29saWQiKSkgKwogIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyYXk5MCIsIHNpemU9MC41KSkgKwogIHRoZW1lKGF4aXMudGlja3MubGVuZ3RoID0gdW5pdCgwLjE4LCAiY20iKSkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAic29saWQiKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2U9InBsYWluIiwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTgsIGFuZ2xlPTApLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2U9InBsYWluIiwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTgsIGFuZ2xlPTApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJwbGFpbiIsIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTEyLCBhbmdsZT0wKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0icGxhaW4iLCBjb2xvcj0iYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT0xNCwgYW5nbGU9MCkpIAojIHByb21vXzFfaGlzdApgYGAKCmBgYHtyIHJlc3VsdHM9ImhpZGUifQojIyBQcm9tb3Rpb24gMgpwcm9tb18yX2hpc3QgPSBnZ3Bsb3QocHJvbW9fMiwgYWVzKHg9U2FsZXNJblRob3VzYW5kcykpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJyZWFrcyA9IGJyZWFrcywgY29sb3I9J2dyYXk4MCcsIGZpbGw9ImdyYXk4MCIpICsgCiAgZ2d0aXRsZSgnUHJvbW90aW9uIDIgU2FsZXMgRGVuc2l0eSBIaXN0cm9ncmFtJykgKwogIHhsYWIoIlNhbGVzIChpbiB0aG91c2FuZHMpIikgKwogIHlsYWIoIkRlbnNpdHkiKSArIAogIGdlb21fZGVuc2l0eShjb2xvciA9ICJibGFjayIsIGZpbGw9Y29sb3JzXzRbM10sICBhbHBoYT0wLjUpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihwcm9tb18yJFNhbGVzSW5UaG91c2FuZHMpLCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3I9J2RhcmtibHVlJywgc2l6ZSA9IDAuOCkgKwogIGFubm90YXRlKCJ0ZXh0Iixjb2xvcj0nZGFya2JsdWUnLCBzaXplID0gMywgeD1tZWFuKHByb21vXzIkU2FsZXNJblRob3VzYW5kcykrMS4yNSwgeT0wLjAxLCAKICAgICAgICAgIGxhYmVsPSBwYXN0ZSgiTWVhbiBTYWxlcyA9Iiwgcm91bmQobWVhbihwcm9tb18yJFNhbGVzSW5UaG91c2FuZHMpLCAyKSksIGFuZ2xlPTkwKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvcj0iZ3JheTkwIiksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyYXk5NCIpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiwgc2l6ZSA9MC41KSkgKwogIHRoZW1lKHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChmaWxsPU5BLCBjb2xvdXIgPSAiZ3JheTkwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAic29saWQiKSkgKwogIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyYXk5MCIsIHNpemU9MC41KSkgKwogIHRoZW1lKGF4aXMudGlja3MubGVuZ3RoID0gdW5pdCgwLjE4LCAiY20iKSkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDAuNSwgbGluZXR5cGUgPSAic29saWQiKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2U9InBsYWluIiwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTgsIGFuZ2xlPTApLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGZhY2U9InBsYWluIiwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTgsIGFuZ2xlPTApKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlPSJwbGFpbiIsIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPTEyLCBhbmdsZT0wKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0icGxhaW4iLCBjb2xvcj0iYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT0xNCwgYW5nbGU9MCkpIAoKIyBwcm9tb18yX2hpc3QKYGBgCgpgYGB7ciByZXN1bHRzPSJoaWRlIn0KIyMgUHJvbW90aW9uIDMKcHJvbW9fM19oaXN0ID0gZ2dwbG90KHByb21vXzMsIGFlcyh4PVNhbGVzSW5UaG91c2FuZHMpKSArIAogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBicmVha3MgPSBicmVha3MsIGNvbG9yPSdncmF5ODAnLCBmaWxsPSJncmF5ODAiKSArIAogIGdndGl0bGUoJ1Byb21vdGlvbiAzIFNhbGVzIERlbnNpdHkgSGlzdHJvZ3JhbScpICsKICB4bGFiKCJTYWxlcyAoaW4gdGhvdXNhbmRzKSIpICsKICB5bGFiKCJEZW5zaXR5IikgKyAKICBnZW9tX2RlbnNpdHkoY29sb3IgPSAiYmxhY2siLCBmaWxsPWNvbG9yc180WzRdLCAgYWxwaGE9MC41KSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4ocHJvbW9fMyRTYWxlc0luVGhvdXNhbmRzKSwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSdkYXJrYmx1ZScsIHNpemUgPSAwLjgpICsKICBhbm5vdGF0ZSgidGV4dCIsY29sb3I9J2RhcmtibHVlJywgc2l6ZSA9IDMsIHg9bWVhbihwcm9tb18zJFNhbGVzSW5UaG91c2FuZHMpKzEuMjUsIHk9MC4wMSwgCiAgICAgICAgICBsYWJlbD0gcGFzdGUoIk1lYW4gU2FsZXMgPSIsIHJvdW5kKG1lYW4ocHJvbW9fMyRTYWxlc0luVGhvdXNhbmRzKSwgMikpLCBhbmdsZT05MCkgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3I9ImdyYXk5MCIpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG9yPSJncmF5OTQiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIsIHNpemUgPTAuNSkpICsKICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoZmlsbD1OQSwgY29sb3VyID0gImdyYXk5MCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gInNvbGlkIikpICsKICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG9yPSJncmF5OTAiLCBzaXplPTAuNSkpICsKICB0aGVtZShheGlzLnRpY2tzLmxlbmd0aCA9IHVuaXQoMC4xOCwgImNtIikpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXk5MCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAwLjUsIGxpbmV0eXBlID0gInNvbGlkIikpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlPSJwbGFpbiIsIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT04LCBhbmdsZT0wKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlPSJwbGFpbiIsIGNvbG9yPSJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT04LCBhbmdsZT0wKSkgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0icGxhaW4iLCBjb2xvcj0iYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT0xMiwgYW5nbGU9MCkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2U9InBsYWluIiwgY29sb3I9ImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9MTQsIGFuZ2xlPTApKSAKIyBwcm9tb18zX2hpc3QKYGBgCgpgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD05LCBmaWcuZnVsbHdpZHRoPVRSVUV9CgpncmlkLmFycmFuZ2UocHJvbW9fMV9oaXN0LCBwcm9tb18yX2hpc3QsIHByb21vXzNfaGlzdCkKYGBgCgoqKipGaWd1cmUgMTAuMDoqKiBTYWxlcyBoaXN0b2dyYW1zIGZvciByZXN0YXVyYW50cyB1c2luZyBQcm9tb3Rpb24gMSAocHVycGxlKSwgUHJvbW90aW9uIDIgKGJsdWUpLCBhbmQgUHJvbW90aW9uIDMgKGdyZWVuKS4qCgo8YnIvPgoKQWxsIHRocmVlIGRlbnNpdHkgaGlzdG9ncmFtcyBhcmUgaW4gdGhlIHNhbWUgc2NhbGUsIG1ha2luZyBpdCBlYXN5IGZvciB1cyB0byBjb21wYXJlIGJvdGggbm9ybWFsaXR5IGFuZCB2YXJpYW5jZS4gV2hlbiB3ZSBleHBsb3JlZCB0aGUgZGF0YSBpbiBQYXJ0IDEsIHRoZSBkYXRhIGZvciBlYWNoIHN1YiBwb3B1bGF0aW9uIChQcm9tb3Rpb24gMSwgUHJvbW90aW9uIDIgYW5kIFByb21vdGlvbiAzKSBoYWQgdmVyeSBzaW1pbGFyIGRpc3RyaWJ1dGlvbnMgKHNlZSAqKlRhYmxlIDIuMCoqKS4gT3VyIGRlbnNpdHkgaGlzdG9ncmFtcyBpbiAqKkZpZ3VyZSAxMC4wKiogY29uZmlybSB0aGF0IHNpbWlsYXJpdHkuCgoqKkFsbCB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zIGRpc3RyaWJ1dGlvbnMgYXJlIGV4dHJlbWVseSBzeW1tZXRyaWMqKi4gQWx0aG91Z2ggbm9uZSBvZiB0aGUgaGlzdG9ncmFtcyBhcmUgcGVyZmVjdGx5IG5vcm1hbCwgd2hpY2ggaXMgZXhwZWN0ZWQgYXMgcGVyZmVjdCBub3JtYWxpdHkgaXMgcmFyZSBpbiBwcmFjdGljZSwgdGhleSBhcmUgc29tZXdoYXQgbm9ybWFsLiBBbGwgaGlzdG9ncmFtcyBoYXZlIG9uZSBtYWpvciBwZWFrIGFyb3VuZCAkNTMkIHRob3VzYW5kIGRvbGxhcnMsIGFuZCBhIHNlY29uZCBtaW5vciBwZWFrIGF0IGFyb3VuZCAkODAkIHRob3VzYW5kIGRvbGxhcnMuIEFsbCBoaXN0b2dyYW1zIHNrZXcgcmlnaHQgd2hpY2ggaXMgZXhwZWN0ZWQgZm9yIG1vc3QgbW9uZXRhcnkgZGlzdHJpYnV0aW9ucy4gVGhlIGRldmlhdGlvbiBmcm9tIG5vcm1hbGl0eSBpcyBub3Qgc2V2ZXJlIGVub3VnaCB0byB3YXJyYW50IGNvbmNlcm4gZm9yIGEgY291cGxlIHJlYXNvbnMuIEZpcnN0bHksIEFOT1ZBIHRlc3RpbmcgaXMgdmVyeSByb2J1c3QgZXNwZWNpYWxseSB3aGVuIHdlIGFyZSB1c2luZyBhIGxhcmdlIHNhbXBsZSBzaXplIG9mICQ1ODgkIHJlc3RhdXJhbnRzLiBTZWNvbmRseSwgdGhlIGRldmlhdGlvbnMgZnJvbSBub3JtYWxpdHkgYXJlIHNpbWlsYXIgYmV0d2VlbiB0aGUgdW5kZXJseWluZyBwb3B1bGF0aW9ucy4KCkFsbCB0aHJlZSBtYXJrZXRpbmcgY2FtcGFpZ25zIHNob3cgdmVyeSBzaW1pbGFyIHZhcmlhbmNlIGZvciAqKipTYWxlc0luVGhvdXNhbmRzKioqIGF0IGFyb3VuZCAkMTYuNzUkLiBWaXN1YWxseSwgYWxsIHRocmVlIGRpc3RyaWJ1dGlvbnMgbG9vayB2ZXJ5IHNpbWlsYXIgaW4gd2lkdGgsIGluZGljYXRpbmcgc2ltaWxhciB2YXJpYW5jZSBhbW9uZyB0aGUgdGhyZWUgbWFya2V0aW5nIGNhbXBhaWducyBzYWxlcy4gQWNjb3JkaW5nIHRvIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0sIGFzIG91ciBzYW1wbGUgc2l6ZSBpbmNyZWFzZXMsIG91ciB2YXJpYW5jZSBkZWNyZWFzZXMuIEJlY2F1c2UgZWFjaCBtYXJrZXRpbmcgY2FtcGFpZ24gcG9wdWxhdGlvbiBoYXMgYXJvdW5kICQxNzAkIHJlc3RhdXJhbnRzIGVhY2gsIG91ciBzeW1tZXRyaWMgdmFyaWFuY2UgY2FuIGJlIHBhcnRseSBhdHRyaWJ1dGVkIHRvIHRoZSByYXRoZXIgbGFyZ2UsIGVxdWFsbHkgcHJvcG9ydGlvbmVkIHVuZGVybHlpbmcgcG9wdWxhdGlvbiBzaXplcy4gSWYgd2UgaGFkIG9uZSB1bmRlcmx5aW5nIHBvcHVsYXRpb24gd2l0aCBhIGRpc3Byb3BvcnRpb25hdGVseSBzbWFsbCBwb3B1bGF0aW9uIHNpemUsIHNheSBQcm9tb3Rpb24gMSBoYWQgJDMwJCByZXN0YXVyYW50cyBpbnN0ZWFkIG9mICQxNzIkLCB3ZSB3b3VsZCBsaWtlbHkgc2VlIGEgdmFyaWFuY2UgdGhhdCB3YXMgbm90IHNpbWlsYXIgdG8gdGhlIG90aGVyIHVuZGVybHlpbmcgcG9wdWxhdGlvbnMuIEx1Y2tpbHkgdGhpcyBpcyBub3QgdGhlIGNhc2UuIFRoZSBnZW5lcmFsICoqcnVsZSBvZiB0aHVtYioqIHVzZWQgaW4gcHJhY3RpY2UgdG8gY2hlY2sgZm9yIHZhcmlhbmNlIHNpbWlsYXJpdHkgaXMgdGhhdCAqKnRoZSBsYXJnZXN0IHNhbXBsZSBzdGFuZGFyZCBkZXZpYXRpb24gc2hvdWxkIGJlIG5vIG1vcmUgdGhhbiB0d2ljZSBhcyBsYXJnZSBhcyB0aGUgc21hbGxlc3Qgc2FtcGxlIHN0YW5kYXJkIGRldmlhdGlvbi4qKiBPdXIgZGF0YSBmb2xsb3dzIHRoaXMgcnVsZS4KCkluIGNvbmNsdXNpb24sIGJvdGggYWxsIHRocmVlIGFzc3VtcHRpb25zIGFyZSBtZXQuCgo8YnIvPgoKIyMjICoqTGltaXRhdGlvbnMqKgoKRnJvbSBvdXIgZXhwbG9yYXRpb24gb2YgdGhlIGRhdGEsIHRoZSBvbmx5IHZhcmlhYmxlIHdpdGggYXNzb2NpYXRpb24gdG8gYSByZXN0YXVyYW50J3MgKioqU2FsZXNJblRob3VzYW5kcyoqKiB3YXMgdGhlIG1hcmtldGluZyBjYW1wYWlnbmVkIHVzZWQsICoqKkFnZU9mU3RvcmUqKiogd2FzIHNob3duIHRvIGhhdmUgbm8gY29ycmVsYXRpb24gaW4gb3VyIEFOQ09WQSB0ZXN0IGFuZCB3aGVuIHdlIGRpZCBhIHNpbXBsZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBjYWxjdWxhdGlvbi4gSG93ZXZlciwgVGhlcmUgbWF5IGJlICoqbHVya2luZyB2YXJpYWJsZXMqKiB0aGF0IGhhdmUgYSBzdHJvbmcgaW5mbHVlbmNlIG9uIGEgcmVzdGF1cmFudCdzICoqKlNhbGVzSW5UaG91c2FuZHMqKiogdGhhdCB3ZXJlIG5vdCBtZWFzdXJlZCBieSB0aGUgY29tcGFueSBpbiBvdXIgc3R1ZHkuIEFsdGhvdWdoICoqKlNhbGVzSW5UaG91c2FuZHMqKiogYW5kIFByb21vdGlvbiBhcmUgYXNzb2NpYXRlZCwgaXQgaXMgaGlnaGx5IGxpa2VseSB0aGF0IHRoZSBtYXJrZXRpbmcgY2FtcGFpZ24gaXMgbm90IHRoZSBvbmx5IHZhcmlhYmxlIHRoYXQgaXMgcmVzcG9uc2libGUgZm9yIGRpZmZlcmVuY2VzIGluIHNhbGVzIGZpZ3VyZXMuCgpGb3IgZXhhbXBsZSwgbWF5YmUgdGhlIGxvd2VyIHNhbGVzIG9ic2VydmVkIGluIHdhcyBkdWUgdG8gdGhhdCB1bmRlcmx5aW5nIHBvcHVsYXRpb24gaGF2aW5nIG1vcmUgcmVzdGF1cmFudHMgaW4gcG9vcmVyIGFyZWFzIHdpdGggcGVvcGxlIHdobyBjYW5ub3QgYWZmb3JkIHRvIGVhdCBvdXQsIG9yIG1heWJlIGFmZmx1ZW50IGFyZWEgdGhhdCBkb24ndCBlYXQgYXQgdGhlIHJlc3RhdXJhbnQgb2Z0ZW4uIFRvIGNvbnRpbnVlLCBtYXliZSB0aGUgbWFya2V0IGRlbW9ncmFwaGljcyBvZiB0aGUgdW5kZXJseWluZyBwb3B1bGF0aW9ucyBhcmUgZGlmZmVyZW50LiBJZiBQcm9tb3Rpb24gMiB3YXMgYSBkaWdpdGFsIG1hcmtldGluZyBjYW1wYWlnbiBhbmQgdGhlIFByb21vdGlvbiAyJ3MgbWFya2V0IGRlbW9ncmFwaGljcyBza2V3ZWQgb2xkZXIgdGhhbiB0aGUgUHJvbW90aW9uIDEgYW5kIFByb21vdGlvbiAyIG1hcmtldHMsIHRoYXQgZGVtb2dyYXBoaWMgZGlmZmVyZW5jZSBtYXkgaGF2ZSBjYXVzZWQgdGhlIGRlY3JlYXNlIGluIHRoZSBlZmZlY3RpdmVuZXNzIG9mIHRoZSBtYXJrZXRpbmcgY2FtcGFpZ24sIG5vdCB0aGUgY2FtcGFpZ24gaXRzZWxmLiBUaGVyZSBhcmUgbWFueSBsdXJraW5nIHZhcmlhYmxlcywgYW5kIG5lYXIgaW1wb3NzaWJsZSB0byBhY2NvdW50IGZvciBhbGwgb2YgdGhlbS4KCklmIHRpbWUgYW5kIGNhcGl0YWwgd2VyZSBpbmNvbnNlcXVlbnRpYWwsIG9uZSB3YXkgaW4gd2hpY2ggdGhlIGNvbXBhbnkgY291bGQgdmV0IG91ciBjb25jbHVzaW9ucyB3b3VsZCBiZSB0byBzd2l0Y2ggdGhlIG1hcmtldGluZyBjYW1wYWlnbnMgZWFjaCByZXN0YXVyYW50IGNvaG9ydCB1c2VzIGFuZCByZWdhdGhlciBzYWxlcyBkYXRhLiBGb3IgaW5zdGFuY2UsIGFsbCByZXN0YXVyYW50cyB0aGF0IHVzZWQgUHJvbW90aW9uIDEgd2lsbCB1c2UgUHJvbW90aW9uIDIsIFByb21vdGlvbiAyIHdpbGwgdXNlIFByb21vdGlvbiAzLCBhbmQgUHJvbW90aW9uIDMgd2lsbCB1c2UgUHJvbW90aW9uIDEuIElmIG91ciBjb25jbHVzaW9uIHRoYXQgUHJvbW90aW9uIDIgbWFya2V0aW5nIGNhbXBhaWduIHdhcyBsZWFzdCBlZmZlY3RpdmUgYXQgaW5jcmVhc2luZyBzYWxlIGhvbGRzLCB3ZSB3b3VsZCBiZSBtb3JlIGNvbmZpZGVuY2UgaW4gdGhlIGVmZmVjdCBvZiB0aGUgbWFya2V0aW5nIGNhbXBhaWduIG9uIHNhbGVzLiBFdmVuIHRob3VnaCB0aGlzIG1heSBhbnN3ZXIgc29tZSBvZiBvdXIgcXVlc3Rpb25zIGFib3V0IGRlbW9ncmFwaGljIGRpZmZlcmVuY2VzIGRpc2N1c3NlZCBhYm92ZSwgd2UgY2FuIG5ldmVyIGFjY291bnQgZm9yIGV2ZXJ5IGx1cmtpbmcgdmFyaWFibGUsIGFuZCB3ZSBjYW4gbmV2ZXIgYmUgZnVsbHkgY2VydGFpbiBhYm91dCBjYXVzYXRpb24sIG9ubHkgc3RyZW5ndGggb2YgYXNzb2NpYXRpb24uIFdlIHdvdWxkIG5lZWQgdG8gZGVzaWduIGFuZCBjb25kdWN0IG1hbnkgbW9yZSBzdHVkaWVzIHRvIHN1Z2dlc3QgY2F1c2F0aW9uLgoKIyMgIHsudW5udW1iZXJlZH0KCjxici8+PGJyLz48YnIvPgo=